Java 8 按属性区分 [英] Java 8 Distinct by property
问题描述
在 Java 8 中,如何使用 Stream
API 通过检查每个对象的属性的独特性来过滤集合?
In Java 8 how can I filter a collection using the Stream
API by checking the distinctness of a property of each object?
例如我有一个 Person
对象列表,我想删除同名的人,
For example I have a list of Person
object and I want to remove people with the same name,
persons.stream().distinct();
将对 Person
对象使用默认的相等性检查,所以我需要类似的东西,
Will use the default equality check for a Person
object, so I need something like,
persons.stream().distinct(p -> p.getName());
不幸的是,distinct()
方法没有这样的重载.不修改 Person
类内部的相等性检查是否可以简洁地做到这一点?
Unfortunately the distinct()
method has no such overload. Without modifying the equality check inside the Person
class is it possible to do this succinctly?
推荐答案
将 distinct
视为 有状态过滤器.这是一个函数,它返回一个谓词,该谓词维护关于它之前看到的内容的状态,并返回给定元素是否第一次被看到:
Consider distinct
to be a stateful filter. Here is a function that returns a predicate that maintains state about what it's seen previously, and that returns whether the given element was seen for the first time:
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()
确实如此.
Note that if the stream is ordered and is run in parallel, this will preserve an arbitrary element from among the duplicates, instead of the first one, as distinct()
does.
(这与这个问题的我的回答基本相同:Java Lambda Stream Distinct() 在任意键上?)
(This is essentially the same as my answer to this question: Java Lambda Stream Distinct() on arbitrary key?)
这篇关于Java 8 按属性区分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!