来自函数引用的谓词(布尔类型)

Tom*_* F. 8 java predicate java-8 functional-interface

我需要使用基于布尔函数的谓词来组合流操作.通过将方法的参数重新抛出为谓词找到了一种解决方法,如下所示:

public <T> Predicate<T> pred(final Predicate<T> aLambda) {
    return aLambda;
}

public List<String> foo() {
    return new ArrayList<String>().stream() //of course, this does nothing, simplified
            .filter(pred(String::isEmpty).negate())
            .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

'pred'方法似乎无能为力,但不是这样:

public List<String> foo() {
    return new ArrayList<String>().stream() 
            .filter((String::isEmpty).negate()) 
            .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

也没有任何内联转换:

public List<String> foo() {
    return new ArrayList<String>().stream() 
            .filter(((Predicate)String::isEmpty).negate())
            .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

似乎工作.失败了

此表达式的目标类型必须是功能接口

在'pred(...)'方法中,花式转换发生了什么?

And*_*lko 7

你可以写一个实用工具方法:

class PredicateUtils {

    public static <T> Predicate<T> not(Predicate<T> predicate) {
        return predicate.negate();
    }

}
Run Code Online (Sandbox Code Playgroud)

并按如下方式使用:

.filter(not(String::isEmpty))
Run Code Online (Sandbox Code Playgroud)

我相信它比铸造更具可读性Predicate<T>:

.filter(((Predicate<String>)String::isEmpty).negate())
Run Code Online (Sandbox Code Playgroud)

虽然我会选择一个简单的lambda:

s -> !s.isEmpty()
Run Code Online (Sandbox Code Playgroud)

pred(...)方法中发生了什么奇特的转换?

您已指定了上下文 - 要使用的类型.例如,a String::isEmpty可以是a Function<String, Boolean>,or Predicate<String>,或my @FunctionalInterface,或其他.

你清楚地说你期待一个Predicate<T>,你会返回一个实例Predicate<T>.编译器现在能够确定您要使用的类型.

  • 你应该在答案的开头放置`s - >!s.isEmpty()` (4认同)

JB *_*zet 6

您可以使用

((Predicate<String>) String::isEmpty).negate()
Run Code Online (Sandbox Code Playgroud)

(注意使用正确的通用类型)

或(首选):

s -> !s.isEmpty()
Run Code Online (Sandbox Code Playgroud)

这更简单,更易读.