Java中如何通过Set从People对象列表按身高去重?
按身高去重People对象的解决方案
你遇到的问题核心在于:默认的HashSet(Collectors.toSet()默认返回的实现)是通过对象的equals()和hashCode()方法来判断唯一性的。你的People类没有重写这两个方法,所以每个People实例都会被视为不同的对象,哪怕它们的身高完全一致,自然无法实现按身高去重。
下面给你几种实用的解决方案,你可以根据自己的业务场景选择:
方法一:使用Collectors.toMap(推荐,灵活可控)
这种方式通过将身高作为键,People对象作为值,遇到重复身高时自定义保留规则(比如保留第一个出现的对象),最后提取值集合即可实现去重。
Set<People> uniquePeople = people.stream() .filter(Objects::nonNull) .collect(Collectors.toMap( People::getHeight, // 以身高作为去重的判断键 person -> person, // 对应存储的People对象 (existingPerson, newPerson) -> existingPerson // 重复时保留第一个对象 )) .values() // 提取所有去重后的People对象 .stream() .collect(Collectors.toSet());
如果你想保留最后一个出现的重复身高对象,只需要把合并函数改成(existing, replacement) -> replacement即可。
方法二:使用自定义比较器的TreeSet
TreeSet会根据自定义的比较器来判断对象是否相等,我们可以指定只比较身高字段来实现去重,同时它还会自动按身高排序。
Set<People> uniquePeople = people.stream() .filter(Objects::nonNull) .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparingDouble(People::getHeight)) ));
注意:这种方式下,两个身高相同的People对象会被视为“相等”,TreeSet只会保留其中一个(具体保留哪个取决于插入顺序和比较器逻辑)。
方法三:重写People类的equals()和hashCode()(谨慎使用)
如果你在业务逻辑中,People对象的相等性本来就应该仅由身高决定,那么可以重写这两个方法,这样你原来的代码就能直接生效。
修改后的People类示例:
class People { private String name; private double height; private int age; // 构造器、getter、setter方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; People people = (People) o; // 仅比较height字段判断是否相等 return Double.compare(people.height, height) == 0; } @Override public int hashCode() { // 仅基于height生成哈希值 return Objects.hash(height); } }
⚠️ 注意:重写这两个方法会影响所有依赖equals()和hashCode()的场景(比如用People作为HashMap的键、其他集合的去重逻辑等),一定要确认这种修改符合所有业务需求后再使用。
内容的提问来源于stack exchange,提问作者Garuuk
相关产品推荐
相关产品推荐

