问题

在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()所做的那样.

(这基本上与我对此问题的答案: Java Lambda Stream Distinct()任意键?)

  相同标签的其他问题

javacollectionsjava-8java-stream