繁体   English   中英

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

[英]Get unique items from List of Objects with a Set in Java

我的人对象看起来像这样

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

首先,给班级命名People是不自然的,更好的名字应该是Person

因此,为了解决您的问题,您只能像这样覆盖equalshashcode来获取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;
}

上面假设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您可以使用toMap收集器完成

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创建一个流,将myList收集到地图实现中,其中Person::getHeight是一个提取地图键的人高的Function.identity()Function.identity()是一个提取地图值的人对象的函数(left, right) -> left)被称为合并功能,这意味着如果两个给定的人具有相同的键(高度),我们将返回第一个人( left )。 相反,在按键冲突的情况下, (left, right) -> right将返回最后一个人。

最后,我们将此处理结果传递给HashSet构造函数以创建Set<Person>

将此任务分为两个子任务。

身高第一组的人:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM