JAVA 8 将谓词提取为字段或方法?
JAVA 8 Extract predicates as fields or methods?
提取具有多种用途的谓词的更简洁方法是什么。方法或 Class 字段?
两个例子:
1.Class 字段
void someMethod() {
IntStream.range(1, 100)
.filter(isOverFifty)
.forEach(System.out::println);
}
private IntPredicate isOverFifty = number -> number > 50;
2.Method
void someMethod() {
IntStream.range(1, 100)
.filter(isOverFifty())
.forEach(System.out::println);
}
private IntPredicate isOverFifty() {
return number -> number > 50;
}
对我来说,现场方式看起来更好一些,但这是正确的方式吗?我有疑问。
要回答,最好为老式 Java 扩展那些 lambda 表达式。你现在可以看到,这是我们在代码中使用的两种方式。所以,答案是,这完全取决于您如何编写特定代码段。
private IntPredicate isOverFifty = new IntPredicate<Integer>(){
public void test(number){
return number > 50;
}
};
private IntPredicate isOverFifty() {
return new IntPredicate<Integer>(){
public void test(number){
return number > 50;
}
};
}
通常 你缓存创建起来很昂贵的东西,这些无状态的 lambdas 不是。无状态 lambda 将为整个管道创建一个实例(在当前实现下)。第一次调用是最昂贵的 - 底层 Predicate
实现 class 将被创建和链接;但这对于无状态和有状态的 lambda 只发生一次。
有状态的 lambda 将为每个元素使用不同的实例,缓存这些元素可能有意义,但您的示例是无状态的,所以我不会。
如果您仍然想要那个(我假设是出于阅读目的),我会在 class Predicates
中进行假设。它也可以在不同的 classes 中重复使用,像这样:
public final class Predicates {
private Predicates(){
}
public static IntPredicate isOverFifty() {
return number -> number > 50;
}
}
您还应该注意到 Predicates.isOverFifty
在 Stream 中的用法和 x -> x > 50
虽然在语义上相同,但会有不同的内存使用。
在第一种情况下,只会创建一个实例(和 class)并提供给所有客户端;而第二个 (x -> x > 50
) 不仅会创建一个不同的实例,还会为它的每个客户端创建一个不同的 class(想想在你的应用程序中不同地方使用的相同表达式)。发生这种情况是因为链接发生在每个 CallSite
- 在第二种情况下 CallSite
总是不同的。
但这是你不应该依赖(甚至可能考虑)的东西 - 这些对象和 classes 可以快速构建和快速被 GC 删除 - 只要适合你的需要 - 使用它。
1) 对于现场情况,您将始终为每个新对象分配谓词。如果您有一些实例,喜欢,服务,那没什么大不了的。但如果这是一个可以是 N 的值对象,这不是一个好的解决方案。还要记住 someMethod()
可能根本不会被调用。一种可能的解决方案是将谓词设为 static
字段。
2) 对于方法用例,每次 someMethod()
调用都会创建一次谓词。 GC后会丢弃它。
提取具有多种用途的谓词的更简洁方法是什么。方法或 Class 字段?
两个例子:
1.Class 字段
void someMethod() {
IntStream.range(1, 100)
.filter(isOverFifty)
.forEach(System.out::println);
}
private IntPredicate isOverFifty = number -> number > 50;
2.Method
void someMethod() {
IntStream.range(1, 100)
.filter(isOverFifty())
.forEach(System.out::println);
}
private IntPredicate isOverFifty() {
return number -> number > 50;
}
对我来说,现场方式看起来更好一些,但这是正确的方式吗?我有疑问。
要回答,最好为老式 Java 扩展那些 lambda 表达式。你现在可以看到,这是我们在代码中使用的两种方式。所以,答案是,这完全取决于您如何编写特定代码段。
private IntPredicate isOverFifty = new IntPredicate<Integer>(){
public void test(number){
return number > 50;
}
};
private IntPredicate isOverFifty() {
return new IntPredicate<Integer>(){
public void test(number){
return number > 50;
}
};
}
通常 你缓存创建起来很昂贵的东西,这些无状态的 lambdas 不是。无状态 lambda 将为整个管道创建一个实例(在当前实现下)。第一次调用是最昂贵的 - 底层 Predicate
实现 class 将被创建和链接;但这对于无状态和有状态的 lambda 只发生一次。
有状态的 lambda 将为每个元素使用不同的实例,缓存这些元素可能有意义,但您的示例是无状态的,所以我不会。
如果您仍然想要那个(我假设是出于阅读目的),我会在 class Predicates
中进行假设。它也可以在不同的 classes 中重复使用,像这样:
public final class Predicates {
private Predicates(){
}
public static IntPredicate isOverFifty() {
return number -> number > 50;
}
}
您还应该注意到 Predicates.isOverFifty
在 Stream 中的用法和 x -> x > 50
虽然在语义上相同,但会有不同的内存使用。
在第一种情况下,只会创建一个实例(和 class)并提供给所有客户端;而第二个 (x -> x > 50
) 不仅会创建一个不同的实例,还会为它的每个客户端创建一个不同的 class(想想在你的应用程序中不同地方使用的相同表达式)。发生这种情况是因为链接发生在每个 CallSite
- 在第二种情况下 CallSite
总是不同的。
但这是你不应该依赖(甚至可能考虑)的东西 - 这些对象和 classes 可以快速构建和快速被 GC 删除 - 只要适合你的需要 - 使用它。
1) 对于现场情况,您将始终为每个新对象分配谓词。如果您有一些实例,喜欢,服务,那没什么大不了的。但如果这是一个可以是 N 的值对象,这不是一个好的解决方案。还要记住 someMethod()
可能根本不会被调用。一种可能的解决方案是将谓词设为 static
字段。
2) 对于方法用例,每次 someMethod()
调用都会创建一次谓词。 GC后会丢弃它。