我知道这可能是一个关于SO的非常基本的问题,但是我想知道Java8中Predicate
和Function
接口之间的区别是什么?
Predicate<String> predicateTest = (s)-> s.length() > 5;
System.out.println(predicateTest.test("Predicate"));
Function<String, Boolean> functionTest = str -> str.length()> 5;
System.out.println(functionTest.apply("Function"));
在我的示例中,两个都返回true
。唯一的区别是调用方式不同?
答案 0 :(得分:32)
Predicate<T>
和Function<T, R>
之间的差异首先Predicate<T>
是严格一个布尔值函数:
_ _ _ _ _ _ _
| |
T --> | predicate | --> boolean
|_ _ _ _ _ _ _|
Function<T, R>
不一定是这样:
_ _ _ _ _ _ _
| |
T --> | function | --> R
|_ _ _ _ _ _ _|
后者会消耗Predicate<T>
所启用的任何类型的对象,但可以改变返回类型。
Predicate<T>
和Function<T, R>
的用例 Predicate<T>
的用例是当您需要一个使用类型为T
类型的参数并返回布尔值的函数时。例如可能是在您要过滤元素流,从满足.filter(predicate).findFirst()
这样的条件的流中找到第一个元素,或者从满足特定条件的流中检查元素是否存在的情况下anyMatch
,noneMatch
,allMatch
等条件。
Function<T, R>
的用例是当您需要一个使用类型为T
的参数并将其转换为类型R
的函数时,例如可能是在致电stream.map(func)
时。
关于您帖子Predicate<String>
和Function<String, Boolean>
中的示例片段,它们所代表的含义是相同的,即它们都代表一个接受String
并返回{ {1}}。但是,前者避免将返回的值从boolean
装箱到boolean
,而后者则没有。
也就是说,这不一定意味着您可以在任何地方使用Boolean
,也可以使用Predicate<String>
,反之亦然。
示例:
当编译时:
Function<String, Boolean>
这不是:
Predicate<String> predicate = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(predicate);
,反之亦然:
这可行:
Function<String, Boolean> function = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(function);
这不是:
Function<String, Boolean> function = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(function);
答案 1 :(得分:6)
在这种情况下没有区别,仅与您可以应用的内容有关。因此,例如allMatch
期望Predicate
,即使在逻辑上他们做相同的事情,也无法传递Function
。
答案 2 :(得分:5)
Aominè的答案涵盖了基本差异。我想补充一点,这两个接口还具有不同的专用默认方法,即可以在任何实现类上调用的方法:
Predicate<T>
Predicate<T> and(Predicate<? super T> other)
-返回一个组成谓词,该谓词表示此谓词和另一个谓词的短路逻辑与。Predicate<T> or(Predicate<? super T> other)
-返回一个组成的谓词,该谓词表示此谓词和另一个谓词的短路逻辑或。negate()
-返回表示该谓词逻辑取反的谓词。Function<T,R>
<V> Function<T,V> andThen(Function<? super R,? extends V> after)
-返回一个组合函数,该函数首先将此函数应用于其输入,然后将after
函数应用于结果。<V> Function<V,R> compose(Function<? super V,? extends T> before)
-返回一个组合函数,该函数首先将before
函数应用于其输入,然后将该函数应用于结果。如您所见,Predicate
具有创建复杂条件的有用方法,就像您在常规if
语句中使用的运算符一样,而Function
具有支持简单链接的方法
答案 3 :(得分:2)
Predicate
只能返回boolean
(test()
的结果),而Function
进行转换并可以返回任何内容(apply()
的结果)
Predicate
用于测试条件。
使用Function
进行转换。
答案 4 :(得分:1)
理论上,Predicate<T>
和Function<T, Boolean>
之间不应有任何功能上的区别。 Predicate
只是一个接受某种类型的对象并返回布尔值的函数。 Function
是一种泛化,可以返回任何类型,而不仅仅是Boolean
。
Java本身中可能有一些实现细节,使它们与众不同,但理论上它们应该相同。
一个例子是接口只能接受Predicate<String>
,而不接受Function<String, Boolean
。
答案 5 :(得分:1)
从技术角度来看,Predicate<T>
只是一个接受T
并返回布尔型原始结果的函数。但是,从使用角度来看,Predicate<T>
与Function<T, Boolean>
完全不同。
我们使用Predicate<T>
进行过滤操作,例如,在流管道中,我们使用大小为Stream<T>
的{{1}},并使用n
对其进行过滤获得大小小于或等于Predicate<T>
的流。同时,流管道中的n
用于执行映射操作,以将Function<T, Boolean>
转换为Stream<T>
。
如您所见,Stream<Boolean>
和Predicate<T>
在技术上是相同的(为简单起见,忽略了包装器Function<T, Boolean>
),但是当放置在特定上下文中时(例如流管道) ,这是完全不同的故事,因为他们每个人都扮演着不同的角色。
答案 6 :(得分:1)
尽管这是一篇过时的文章,但我将为新手总结它们之间的差异
谓词::要实施条件检查,我们应使用谓词。
功能:要执行某些操作并返回一些结果,我们应该使用功能
谓词:谓词可以采用一种表示输入类型或参数类型的类型参数。
函数:函数可以接受2个类型参数,第一个代表输入类型参数类型,第二个代表返回类型。
谓词:谓词定义了一个称为test()的抽象函数。使用谓词时,您可以说“测试此条件”或“测试此条件”
函数:函数定义了一个称为apply()的抽象函数。使用功能时,您可以说“应用此功能”或“应用此功能”
谓词:始终返回布尔值。
函数:函数可以返回任何类型的值。
有时人们称谓词为Function的谓词特殊情况。 它们之间的另一个区别是,它们在各自的界面中包含不同类型的默认方法和静态方法。