在 Java 8 中,如何使用 Stream
API 通过检查每个对象的属性的独特性来过滤集合?
例如,我有一个 Person
对象列表,我想删除同名的人,
persons.stream().distinct();
将对 Person
对象使用默认相等检查,所以我需要类似的东西,
persons.stream().distinct(p -> p.getName());
不幸的是 distinct()
方法没有这样的重载。如果不修改 Person
类中的相等性检查,是否可以简洁地做到这一点?
最佳答案
将 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()
会。
(这本质上与 my answer 对这个问题:Java Lambda Stream Distinct() on arbitrary key? 相同)
关于Java 8 按属性区分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23699371/