RichK RichK - 6 months ago 494
Java Question

Java 8 Distinct by property

In Java 8 how can I filter a collection using the

API by checking the distinctness of a property of each object?

For example I have a list of
object and I want to remove people with the same name,;

Will use the default equality check for a
object, so I need something like, -> p.getName());

Unfortunately the
method has no such overload. Without modifying the equality check inside the
class is it possible to do this succinctly?


I finally figured out a nice way to do this. Consider distinct to be a stateful filter. Write function that returns a predicate that also maintains state about what it's seen previously, and returns whether the given element was seen for the first time:

public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Map<Object,Boolean> seen = new ConcurrentHashMap<>();
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;

Then you can write: -> p.getName());

Note: this is essentially the same as my answer to this question:Java Lambda Stream Distinct() on arbitrary key?