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.

+3


source to share


2 answers


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.

+2


source


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)

      

+1


source







All Articles