使用Predicate或函数作为Java流过滤器有什么区别?

AdH*_*nem 12 predicate java-8 java-stream

因此,假设我在流上使用了一些随机过滤器,最直接的方法是直接输入谓词:

x.stream().filter(e -> e % 2 == 0)
Run Code Online (Sandbox Code Playgroud)

我也可以简单地做一个参考并提前定义谓词:

Predicate<Integer> isEven = e -> e % 2 == 0;
...
x.stream().filter(isEven)
Run Code Online (Sandbox Code Playgroud)

但我也可以使用一个函数:

private static boolean isEven(Integer integer) {
    return integer % 2 == 0;
}
...
x.stream().filter(MyClass::isEven)
Run Code Online (Sandbox Code Playgroud)

据我所知,谓词当然更有限,而功能可能有副作用等.但由于像Venkat Subramaniam这样的人使用后者的解决方案,我真的很想知道:这里的主要区别是什么?

Grz*_*rek 12

没有!与方法参考相比,谓词并没有真正的限制!事实上,这些都是一样的!

只需看看filter()功能签名: filter(Predicate<? super T> predicate)

让我们考虑你的例子:

x.stream().filter(e -> e % 2 == 0)

Predicate<Integer> isEven = e -> e % 2 == 0;
...
x.stream().filter(isEven)
Run Code Online (Sandbox Code Playgroud)

第一个只是后者的内联版本.

private static boolean isEven(Integer integer) {
return integer % 2 == 0;
}
...
x.stream().filter(MyClass::isEven)
Run Code Online (Sandbox Code Playgroud)

在这里你可以看到Method References实际行动.MR只是一种语法糖,允许您根据已有的函数定义Lambda Expression.

在一天结束时,所有这些表达式都成为Predicate功能接口的相同实现.

此外,您还可以使用右侧的块语法在Lambda表达式中执行副作用,但通常不建议:

e -> {
    //side effects here
    return e % 2 == 0;
}
Run Code Online (Sandbox Code Playgroud)


Han*_*k D 5

从构建可重用谓词库的角度来看,返回布尔值的函数库是比静态最终谓词实例库更通用的谓词集合。为什么?

考虑一个包含以下内容的库:

public static boolean isEven(int i) { return i -> i % 2 == 0; }
Run Code Online (Sandbox Code Playgroud)

对比

public static final Predicate<Integer> IS_EVEN = i -> i % 2 == 0; 
Run Code Online (Sandbox Code Playgroud)
  • 如果库函数命名得好,它们读起来会更好。在长时间缺席后重新访问代码时,扫描filter(MyLib::isEven)filter(i -> i % 2 == 0)filter(MyLib::isEven)告诉您正在调用的内容更容易,而filter(MyLib.IS_EVEN)不会
  • 如果您只想调用库函数而不是将其用作谓词,则它更具可读性。MyLib.isEven(i)扫描比MyLib.IS_EVEN.test(i)
  • 如果您需要使用 anIntPredicate而不是Predicate<Integer>Guava Predicate<Integer>、 Apache Collections4Predicate<Integer>等,您只需继续使用库函数即可MyLib::isEven。对于static final Predicate<Integer>实例,您必须通过执行来转换它MyLib.IS_EVEN::test(无论如何您最终都会使用方法引用)

同样的推理适用于所有功能类型。编写函数。它们可以应用于任何与具有简单方法引用的签名相匹配的函数类型。