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后会丢弃它。