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

What is the difference between a Predicate and a Function Interface in Java8?

我知道这可能是关于 SO 的一个非常基本的问题,但我想知道 Predicate 和 Java8 中的 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。唯一的问题是调用方式不同?

在这种情况下没有区别,只对你可以申请的事情有影响。因此,例如 allMatch 期望 Predicate,你不能传递 Function,即使逻辑上它们做同样的事情。

真的没有区别。

从理论上讲,Predicate<T>Function<T, Boolean> 之间应该没有任何功能差异。 Predicate 只是一个接受某种类型对象和 return 布尔值的函数。 Function 是一种泛化,它可以 return 任何类型,而不仅仅是 Boolean

Java 本身可能存在使它们不同的实现细节,但理论上它们应该相同。

例如,如果一个接口只能接受 Predicate<String>,而不是 Function<String, Boolean

Predicate<T>Function<T, R> 之间的区别

首先 Predicate<T> 严格来说 一个布尔值函数:

         _ _ _ _ _ _ _ 
        |             |
  T --> |  predicate  | --> boolean
        |_ _ _ _ _ _ _|   

Function<T, R> 不一定如此:

         _ _ _ _ _ _ _ 
        |             |
  T --> |   function  | --> R
        |_ _ _ _ _ _ _| 

后者可以像 Predicate<T> 启用的那样使用任何类型的对象,但可以 在 return 类型中变化

Predicate<T>Function<T, R>

的用例

Predicate<T> 的用例是当您需要一个函数使用一个 T 类型的参数并且 return 是一个布尔值时。例如这可能是在这样的情况下,你想要过滤元素流,从流中找到第一个满足条件 .filter(predicate).findFirst() 的元素,或者检查流中是否存在满足特定条件的元素anyMatchnoneMatchallMatch 等条件

Function<T, R> 的用例是当您需要一个函数使用一个 T 类型的参数并将其转换为 R 类型时,例如可能是在调用 stream.map(func).

您的代码段说明:

关于您 post 中的示例片段,Predicate<String>Function<String, Boolean> 就它们所代表的内容而言是相同的,即它们都代表采用 [=35 的函数=] 和 returning boolean。但是,前者避免将 returned 值从 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);

这不是:

Predicate<String> predicate = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(predicate);

一个Predicate只能return一个booleantest()的结果),而Function做一个转换,可以return任何东西(apply() 的结果)。

A Predicate 用于测试条件。

一个Function用来做一个转换。

Aominè 的回答涵盖了基本差异。我想补充一点,这两个接口也有不同的专用默认方法,即您可以在任何实现 class:

上调用的方法
  • Predicate<T>
    • Predicate<T> and(Predicate<? super T> other) - Returns 表示此谓词与另一个谓词的短路逻辑与的组合谓词。
    • Predicate<T> or(Predicate<? super T> other) - Returns 表示此谓词与另一个谓词的短路逻辑或的组合谓词。
    • negate() - Returns 表示该谓词逻辑否定的谓词。
  • Function<T,R>
    • <V> Function<T,V> andThen(Function<? super R,? extends V> after) - Returns 一个复合函数,首先将此函数应用于其输入,然后将 after 函数应用于结果。
    • <V> Function<V,R> compose(Function<? super V,? extends T> before) - Returns 一个复合函数,它首先将 before 函数应用于其输入,然后将此函数应用于结果。

如您所见,Predicate 具有创建复杂条件的有用方法,很像您在常规 if 语句中使用的运算符,而 Function 具有支持的方法简单的链接。

从技术角度来看,Predicate<T> 只是一个接受 T 并返回布尔原始结果的函数。但是,从用法的角度来看,Predicate<T>Function<T, Boolean>.

是完全不同的概念

我们使用 Predicate<T> 来执行过滤操作,例如,在流管道中,我们采用大小 nStream<T>,使用 [=10= 对其进行过滤] 以获得大小小于或等于 n 的流。同时,使用流管道中的Function<T, Boolean>进行映射操作,将Stream<T>转换为Stream<Boolean>

如您所见,Predicate<T>Function<T, Boolean> 在技术上是相同的(为简单起见忽略包装器 Boolean),但是当放在特定上下文中时(流管道例如),这是完全不同的故事,因为他们每个人都扮演着不同的角色。

虽然很老post但是我会总结一下它们之间的区别给新手

Predicate: 要实现条件检查 我们应该使用 Predicate.

功能:执行某些操作并return一些结果我们应该使用功能

Predicate: Predicate 可以接受一个类型参数,表示输入类型或参数类型。

函数:函数可以接受2个类型参数,第一个代表输入类型参数类型,第二个代表return类型。

Predicate: Predicate 定义了一个名为 test() 的抽象函数。使用谓词时,您可以说 "test this condition" 或 "Testing this condition"

函数:函数定义了一个名为apply()的抽象函数。使用函数时,您可以说 "apply this function" 或 "applying this function"

谓词:总是return布尔值。

函数:函数可以return任何类型的值。

有时人们称函数为谓词特例。 它们之间的另一个区别是它们在各自的接口中包含不同类型的默认方法和静态方法