I often find myself in the need to filter a Stream
or to use a predicate that checks if a given field has a given value.
Say for example I have this POJ
There is no such builtin factory method, which you can easily check by looking at all usages of Predicate within the JFC and look for “Methods in … that return Predicate”. Besides the methods within Predicate itself, there is only Pattern.asPredicate() which returns a Predicate
.
Before you’re going to implement such a factory method, you should ask yourself whether it’s really worth it. What makes your lambda expression in .filter(a -> Objects.equals(a.getField(), someValue))
look complicated, is the use of Objects.equals
which is not necessary when you can predict for at least one argument whether it is null
. Since here, someValue
is never null
, you can simplify the expression:
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()))
…
If you still want to implement the factory method and win a price for creatively using what is already there, you can use:
public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) {
return f.andThen(Predicate.isEqual(value)::test)::apply;
}
However, for production code, I’d rather recommend an implementation like this:
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));
}
This factors out the test whether the constant is null
to simplify the operation that will be performed in each test. So it still doesn’t need Objects.equals
. Note that Predicate.isEqual
does similar.