是否有一种方便的方法来创建谓词来测试字段是否等于给定值?

问题描述 投票:16回答:2

我经常发现自己需要过滤Stream或使用谓词检查给定字段是否具有给定值。

例如,我有这个POJO:

public class A {
    private Integer field;

    public A(final Integer field) {
        this.field = field;
    }

    public Integer getField() {
        return field;
    }
}

而且我想根据Stream的值过滤对象的field

    final Integer someValue = 42;
    Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null))
            .filter(a -> Objects.equals(a.getField(), someValue))
            ...

[是否有一种方便的方法来为filter方法生成谓词?我注意到这里有Predicate.isEqual,但不符合需要。

我很容易这样写:

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) {
    return v -> Objects.equals(value, f.apply(v));
}

并将其用作:

    Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null))
            .filter(isEqual(A::getField, someValue))
            ...

但是如果可能的话,我希望重用JDK中的现有方法。

java functional-programming java-8 predicate
2个回答
11
投票

没有这样的内置工厂方法,可以通过查看all usages of Predicate within the JFC并查找“ ...中返回谓词的方法”来轻松检查。除了Predicate本身中的方法外,只有Predicate返回一个Predicate

在实施这种工厂方法之前,应先问问自己是否真的值得。使Pattern.asPredicate()中的lambda表达式看起来很复杂的原因是Pattern.asPredicate()的使用,当您可以预测至少一个参数是否为Predicate时,则不必使用。由于这里.filter(a -> Objects.equals(a.getField(), someValue))从不Objects.equals,因此可以简化表达式:

null

如果您仍然想实现工厂方法并使用已有的东西创造性地赢得价格,则可以使用:

someValue

但是,对于生产代码,我宁愿推荐这样的实现:

null

这排除了测试是否为常数final Integer someValue = 42; Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) .filter(a -> someValue.equals(a.getField())) … ,以简化将在每个测试中执行的操作。因此它仍然不需要public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { return f.andThen(Predicate.isEqual(value)::test)::apply; } 。请注意,public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { return value==null? t -> f.apply(t)==null: t -> value.equals(f.apply(t)); } 的作用类似。


0
投票

在Java 8及更高版本中,您现在可以使用null

© www.soinside.com 2019 - 2024. All rights reserved.