在Java 8中,我如何使用流API通过检查每个对象的属性的清晰度来过滤一个集合?
例如,我有一个Person对象列表,我想删除同名的人,
persons.stream().distinct();
将对Person对象使用默认的相等性检查,所以我需要这样的东西,
persons.stream().distinct(p -> p.getName());
不幸的是,distinct()方法没有这样的重载。如果不修改Person类内部的相等检查,是否可以简洁地做到这一点?
在Java 8中,我如何使用流API通过检查每个对象的属性的清晰度来过滤一个集合?
例如,我有一个Person对象列表,我想删除同名的人,
persons.stream().distinct();
将对Person对象使用默认的相等性检查,所以我需要这样的东西,
persons.stream().distinct(p -> p.getName());
不幸的是,distinct()方法没有这样的重载。如果不修改Person类内部的相等检查,是否可以简洁地做到这一点?
当前回答
我们也可以使用RxJava(非常强大的响应式扩展库)
Observable.from(persons).distinct(Person::getName)
or
Observable.from(persons).distinct(p -> p.getName())
其他回答
如果你想要名单,下面是最简单的方法
Set<String> set = new HashSet<>(persons.size());
persons.stream().filter(p -> set.add(p.getName())).collect(Collectors.toList());
此外,如果您想要查找不同的或唯一的名称列表,而不是Person,您也可以使用以下两个方法。
方法一:使用区别
persons.stream().map(x->x.getName()).distinct.collect(Collectors.toList());
方法二:使用HashSet
Set<E> set = new HashSet<>();
set.addAll(person.stream().map(x->x.getName()).collect(Collectors.toList()));
您可以在Eclipse Collections中使用distinct(HashingStrategy)方法。
List<Person> persons = ...;
MutableList<Person> distinct =
ListIterate.distinct(persons, HashingStrategies.fromFunction(Person::getName));
如果可以重构人员以实现Eclipse Collections接口,则可以直接调用列表上的方法。
MutableList<Person> persons = ...;
MutableList<Person> distinct =
persons.distinct(HashingStrategies.fromFunction(Person::getName));
HashingStrategy只是一个策略接口,允许您定义equals和hashcode的自定义实现。
public interface HashingStrategy<E>
{
int computeHashCode(E object);
boolean equals(E object1, E object2);
}
注意:我是Eclipse Collections的提交者。
因为每个人都在分享他们自己的想法和实施方法,我也有一个,它不是一个有效的方法,但它是有效的:
Set<String> personNameList = personList.stream().
map(tempPerson->tempPerson.getName()).collect(Collectors.toSet());
personList.stream().
collect(()->new ArrayList<Person>(),
(l1,p)->{
if(!personNameList.contains(p.getName())) {
l1.add(p);
}
}, ArrayList::addAll);
如果可以的话,我推荐使用Vavr。有了这个库,你可以做以下事情:
io.vavr.collection.List.ofAll(persons)
.distinctBy(Person::getName)
.toJavaSet() // or any another Java 8 Collection
Set<YourPropertyType> set = new HashSet<>();
list
.stream()
.filter(it -> set.add(it.getYourProperty()))
.forEach(it -> ...);