一尘不染

Java 8按属性区分

java

在Java 8中,如何Stream通过检查每个对象的属性的不同性来使用API 过滤集合?

例如,我有一个Person对象列表,我想删除同名的人,

persons.stream().distinct();

将对对象使用默认的相等性检查Person,所以我需要类似的东西,

persons.stream().distinct(p -> p.getName());

不幸的是,该distinct()方法没有这种过载。如果不修改Person类内部的相等性检查,是否可以简洁地做到这一点?


阅读 408

收藏
2020-02-27

共1个答案

一尘不染

考虑distinct做一个有状态过滤器。这是一个函数,该函数返回一个谓词,该谓词保持先前状态的状态,并返回是否第一次看到给定元素:

public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return t -> seen.add(keyExtractor.apply(t));
}

然后你可以编写:

persons.stream().filter(distinctByKey(Person::getName))

请注意,如果流是有序的并并行运行,则它将保留重复项中的任意元素,而不是第一个重复元素distinct()

2020-02-27