Java 8 Streams: simplifying o1 & # 8594; Objects.equals (o1.getSome (). GetSomeOther (), o2.getSome (). GetSomeOther ()) on a stream
Given the following code:
stream.filter(o1 -> Objects.equals(o1.getSome().getSomeOther(),
o2.getSome().getSomeOther())
How can this be simplified?
Is there some function equals
that allows you to first extract the key as is Comparator.comparing
, which the key-extractor function takes?
Note that the code ( getSome().getSomeOther()
) itself is actually generated from the schema.
source to share
EDIT: (after discussion with a colleague and after reviewing: Is there a convenient method for generating a predicate that checks if a field matches a given value? )
We have now moved on to the following functional reusable 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;
}
The filtering now looks like this:
stream.filter(property(t -> t.getSome().getSomeOther()).like(o2))
What I like about this solution in regards to the solution before: it explicitly separates the extraction of the property and the creation of itself Predicate
, and it more clearly indicates what is going on.
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);
}
which results in the following usage:
stream.filter(isEqual(o2, t -> t.getSome().getSomeOther())
but I'm happier if someone has a better solution.
source to share
I think your approach to the question is more readable than your answer. And I also think using inline lambdas is ok as long as the lambda is simple and short.
However, for ease of maintenance, readability, debugging, and validation, I always go with the logic I would use in a lambda (predicate or function) for one or more methods. In your case, I would do:
class YourObject {
private Some some;
public boolean matchesSomeOther(YourObject o2) {
return this.getSome().matchesSomeOther(o2.getSome());
}
}
class Some {
private SomeOther someOther;
public boolean matchesSomeOther(Some some2) {
return Objects.isEqual(this.getSomeOther(), some2.getSomeOther());
}
}
Using these methods, your predicate now becomes trivial:
YourClass o2 = ...;
stream.filter(o2::matchesSomeOther)
source to share