2016-04-22 68 views
8

因此,假如我用一些随机的过滤器上的流时,最简单的方法就是直接输入谓词:使用谓词或函数作为Java流过滤器有什么区别?

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

除了我可以简单地做一个参考,并预先定义谓词:

Predicate<Integer> isEven = e -> e % 2 == 0; 
... 
x.stream().filter(isEven) 

但我也用一个函数:

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

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

回答

11

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

试想一下,在filter()函数签名: filter(Predicate<? super T> predicate)

而且我们认为您的例子:

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

Predicate<Integer> isEven = e -> e % 2 == 0; 
... 
x.stream().filter(isEven) 

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

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

,在这里你可以看到在行动Method References。 MR只是一个语法糖,允许您基于已有的函数定义Lambda表达式。

在一天结束时,所有这些表达式都变成Predicate函数接口的相同实现。

此外,您还可以使用右侧块语法执行你的Lambda表达式的副作用,但它一般不建议:

e -> { 
    //side effects here 
    return e % 2 == 0; 
} 
+0

我看到,如果没有MR,我们只能定义关于其重用性的实际上有限的谓词。所以这就产生了一个问题:更简洁的写作方式是什么?使用MR,谓词或实际陈述本身? – AdHominem

+1

@AdHominem它取决于你的上下文。如果你真的不想复用你的谓词,那么只需坚持一个简单的lambda表达式,但是如果你要继续使用它,我建议在一些utils类中创建一个静态的Predicate实例,而不必创建一个方法本身 –

4

当它从视图建立一个库点看可重复使用的谓词,返回一个布尔值的函数库比静态最终谓词实例库更多用途的谓词集合。为什么?

考虑包含以下库:

public static boolean isEven(int i) { return i -> i % 2 == 0; } 

public static final Predicate<Integer> IS_EVEN = i -> i % 2 == 0; 
  • 如果库函数的命名很好,他们读好。当久别重访代码更容易扫描filter(MyLib::isEven)filter(i -> i % 2 == 0)filter(MyLib::isEven)告诉你到底被调用了什么,而filter(MyLib.IS_EVEN)
  • 如果你只是想打电话,而不是把它作为一个谓语的库函数,它更可读。MyLib.isEven(i)扫描速度比MyLib.IS_EVEN.test(i)
  • 如果您需要使用IntPredicate代替Predicate<Integer>一个番石榴Predicate<Integer>,阿帕奇Collections4 Predicate<Integer>等,用库函数好你只是继续做MyLib::isEven。随着static final Predicate<Integer>情况下,你将不得不做MyLib.IS_EVEN::test将其转换(和你最终使用的方法参考反正)

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

相关问题