使用Java中的Set从对象列表中获取唯一项

时间:2018-04-17 20:49:49

标签: java arraylist

我的人物对象看起来像这样

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() );

2 个答案:

答案 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());

或者出于任何原因,您不想覆盖equalshashcode,您可以使用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());