Java 8 按属性区分

标签 java collections java-8 java-stream distinct-values

在 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/

相关文章:

Java - 多线程增量

java - 卡夫卡流-TimeoutException : Expiring * record(s) for TOPIC:* ms has passed since batch creation

java - 当我对 List 进行排序时,它的迭代器会发生什么?

java - 通过使用 Java 8 流对其进行排序将集合转换为 Map

Java8流查找多个值并返回 boolean 值

java - 为一个 JButton 提供两种不同的操作

java - 清空(套接字的)InputStream

C# MongoDB 和更新项目列表

java - 在两个列表中查找额外对象的最佳方法

java - 使用 CompletableFuture 时以下有什么问题?