【问题标题】:Predicate from Function Reference (of boolean type)来自函数引用的谓词(布尔类型)
【发布时间】:2018-01-30 14:56:22
【问题描述】:

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

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());
}

“pred”方法似乎什么都不做,但不是这样:

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

也没有任何在线转换:

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

似乎有效。失败并出现错误

此表达式的目标类型必须是函数式接口

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

【问题讨论】:

    标签: java java-8 predicate functional-interface


    【解决方案1】:

    你可以写一个实用方法:

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

    并按如下方式使用:

    .filter(not(String::isEmpty))
    

    我相信它比转换为 Predicate&lt;T&gt; 更具可读性:

    .filter(((Predicate<String>)String::isEmpty).negate())
    

    虽然我会使用一个简单的 lambda:

    s -> !s.isEmpty()
    

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

    您已经指定了一个上下文 - 要使用的类型。例如,String::isEmpty 可以是Function&lt;String, Boolean&gt;,或Predicate&lt;String&gt;,或我的@FunctionalInterface,或其他。

    您明确表示您期待Predicate&lt;T&gt;,并且您将返回Predicate&lt;T&gt; 的一个实例。编译器现在能够确定您要使用的类型。

    【讨论】:

    • 你应该把s -&gt; !s.isEmpty()放在答案的开头……
    【解决方案2】:

    你可以使用

    ((Predicate<String>) String::isEmpty).negate()
    

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

    或(首选):

    s -> !s.isEmpty()
    

    这样更简单易读。

    【讨论】:

      【解决方案3】:

      您的第三个版本几乎可以使用:

      Arrays.<String>asList("Foo", "Bar", "").stream() 
              .filter(((Predicate<String>)String::isEmpty).negate())
              .collect(Collectors.toList());
      

      这似乎编译得很好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 2023-01-24
        • 1970-01-01
        • 1970-01-01
        • 2020-01-05
        相关资源
        最近更新 更多