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

Nul*_*ter 27 java predicate function java-8

我知道这可能是一个非常基本的问题,但我想知道Java8中的a 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"));
Run Code Online (Sandbox Code Playgroud)

这里在我的例子中都返回true.唯一的问题是呼叫的方式是不同的?

Ous*_* D. 33

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

首先,a Predicate<T>严格的布尔值函数:

         _ _ _ _ _ _ _ 
        |             |
  T --> |  predicate  | --> boolean
        |_ _ _ _ _ _ _|   
Run Code Online (Sandbox Code Playgroud)

虽然这不一定适用于Function<T, R>:

         _ _ _ _ _ _ _ 
        |             |
  T --> |   function  | --> R
        |_ _ _ _ _ _ _| 
Run Code Online (Sandbox Code Playgroud)

后者与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并返回boolean.但是,前者避免将返回值装箱boolean,Boolean而后者则没有.

也就是说,这并不一定意味着你可以使用a,Predicate<String>你也可以使用a Function<String, Boolean>,反之亦然.

例:

虽然这编译:

Predicate<String> predicate = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(predicate);
Run Code Online (Sandbox Code Playgroud)

这不是:

Function<String, Boolean> function = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(function);
Run Code Online (Sandbox Code Playgroud)

反之亦然:

虽然这有效:

Function<String, Boolean> function = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(function);
Run Code Online (Sandbox Code Playgroud)

这不是:

Predicate<String> predicate = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(predicate);
Run Code Online (Sandbox Code Playgroud)

  • 你还可以提到`Predicate`有默认方法`和()`,`或()`和`negate()`这对条件有意义,而`Function`的默认方法对于过滤/链接更有意义. (3认同)
  • @Eugene这就像有人创建一个新的`List`和一个新的`Set`,打印他们的`size()`,然后询问有什么区别.当然,没有:两者的大小都是"0".说*在这种情况下*"没有差别"可能不是"错误的"(我认为我们不必争论这一点),但它至少会误导**.在这两种情况下,我们都在谈论使用不同方法的不同类型,我认为从*使用*的角度来明确它们的差异是很重要的. (3认同)

Eug*_*ene 7

在这种情况下,没有区别,只对您可以申请的事项有用.所以例如allMatch期望a Predicate,你不能传递Function,即使逻辑上他们做同样的事情.

  • 使用`myFunction :: apply`可能仍然有效 (2认同)
  • 虽然这可能不是"讨论"事情的正确场所(如果你愿意,我们可以进行聊天).但是鉴于你对其他答案的评论,*这个*答案至少可以提出为什么不同界面存在的问题(我认为这是一个很好的问题,有一些有趣的技术怪癖).可以这么说,他们可以省略`Predicate`,并且在`anyMatch`等方法中只需要一个`Function <T,Boolean>`.(暂时搁置`null`问题). (2认同)

Nat*_*ski 5

确实没有什么区别。

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

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

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

  • 这个答案似乎是假设性的,而不是基于证据的。有很多“理论上”“应该”等。考虑更好地研究你的答案并提供证据而不是猜测。 (4认同)

Jen*_*ann 5

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

  • Predicate<T>
    • Predicate<T> and(Predicate<? super T> other) - 返回一个组合谓词,表示该谓词和另一个谓词的短路逻辑AND.
    • Predicate<T> or(Predicate<? super T> other) - 返回一个组合谓词,表示该谓词与另一个谓词的短路逻辑OR.
    • 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具有支持简单链接的方法.