Java 8 Streams : simplifying o1 -> Objects. equals(o1.getSome().getSomeOther(), o2.getSome().getSomeOther()) in the stream
Given the following code:
stream.filter(o1 -> Objects.equals(o1.getSome().getSomeOther(),
o2.getSome().getSomeOther())
How can this be simplified?
Are there some equals-utilities
that let you extract a key first, like Comparator.comparing
Same as Which accepts the key extractor function?
Note that the code itself (getSome().
getSomeOther())
is actually generated from the pattern.
Solution
Edit: (After discussing and revisiting with colleagues: Is there a convenience method to create a Predicate that tests if a field equals a given value?)
We now have the following reusable functional interface:
@FunctionalInterface
public interface Property<T, P> {
P extract(T object);
default Predicate<T> like(T example) {
Predicate<P> equality = Predicate.isEqual(extract(example));
return (value) -> equality.test(extract(value));
}
}
and the following static convenience method:
static <T, P> Property<T, P> property(Property<T, P> property) {
return property;
}
Filtering now looks like:
stream.filter(property(t -> t.getSome().getSomeOther()).like(o2))
What I like about this solution compared to the previous solution: it clearly separates the extraction of properties from the creation of Predicate
itself, and speaks more clearly about what is happening.
Previous solution:
<T, U> Predicate<T> isEqual(T other, Function<T, U> keyExtractFunction) {
U otherKey = keyExtractFunction.apply(other);
return t -> Objects.equals(keyExtractFunction.apply(t), otherKey);
}
This results in the following usage:
stream.filter(isEqual(o2, t -> t.getSome().getSomeOther())
But I’d be happier if someone had a better solution.