Java8中的谓词和函数接口有什么区别?

时间:2018-07-20 15:00:46

标签: java function java-8 predicate

我知道这可能是一个关于SO的非常基本的问题,但是我想知道Java8中PredicateFunction接口之间的区别是什么?

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。唯一的区别是调用方式不同?

7 个答案:

答案 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()这样的条件的流中找到第一个元素,或者从满足特定条件的流中检查元素是否存在的情况下anyMatchnoneMatchallMatch等条件。

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只能返回booleantest()的结果),而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的谓词特殊情况。 它们之间的另一个区别是,它们在各自的界面中包含不同类型的默认方法和静态方法