我的人物对象看起来像这样
class People {
this.name,
this.height,
this.age
}
我有一个数据库查询的列表,如此
List<People> people = DAO.queryAllPeople();
返回100个人
然后我想要只有高度独特的人
Set<People> uniquePeople = list
.stream()
.map(people -> people)
.filter(Objects::nonNull)
.collect( Collectors.toSet() );
但是这会返回所有对象,有没有办法让人们按身高分明?
编辑这是我想要的,但我想要Person对象,所以我可以在循环时调用get方法
Set<String> people = people
.stream()
.map(People::getHeight)
.filter(Objects::nonNull)
.collect( Collectors.toSet() );
答案 0 :(得分:1)
首先,命名一个类People
并不自然,更好的名称是Person
。
正如,为了解决您的问题,您可以覆盖equals
hashcode
height
,只有这样:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return height == person.height;
}
@Override
public int hashCode() {
return height;
}
以上假设高度为int
字段。如果相反,它是Integer
,那么你需要像这样实现它:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return height != null ? height.equals(person.height) : person1.height == null;
}
@Override
public int hashCode() {
return height != null ? height.hashCode() : 0;
}
现在,你可以这样做:
Set<People> uniquePeople =
myList.stream()
.filter(Objects::nonNull)
.collect(Collectors.toSet());
或者出于任何原因,您不想覆盖equals
和hashcode
,您可以使用the toMap
collector来执行此操作。
Set<Person> values = new HashSet<>(myList.stream()
.collect(Collectors.toMap(Person::getHeight, Function.identity(),
(left, right) -> left))
.values());
解密上面的代码片段:
myList.stream()
.collect(Collectors.toMap(Person::getHeight, Function.identity(),
(left, right) -> left))
.values()
这会创建一个从myList
收集到地图实现的流,其中Person::getHeight
是一个提取地图键的人物高度的函数,Function.identity()
是一个提取人物对象的函数对于地图值,(left, right) -> left)
被称为合并函数,意味着如果两个给定的人具有相同的键(高度),则返回第一个人(left
)。相反,(left, right) -> right
将在关键冲突的情况下返回最后一个人。
最后,我们将此处理的结果传递给HashSet
构造函数以创建Set<Person>
。
答案 1 :(得分:1)
将此任务拆分为两个子任务。
第一组人员身高:
Map<Integer, List<People>> groups = list.stream()
.collect(Collectors.groupingBy(People::getHeight);
然后找出哪些组只有一个人:
groups.entrySet().stream()
.filter(e -> e.getValue().size() == 1) // use only groups with one person
.map(e -> e.getValue().get(0))
.collect(Collectors.toList());