java中object类通过equals()和hashcode()方法支撑集合去重;hashset依赖二者协同判断重复,自定义类必须同时重写;linkedhashset保持顺序,treeset依赖comparable;list需手动去重。

Java 中 Object 类本身不能直接实现去重,但它是所有类的父类,提供了 equals() 和 hashCode() 两个关键方法——集合框架(尤其是 Set 系列)正是依赖这两个方法来判断对象是否重复。
HashSet 去重依赖 equals + hashCode 的协同机制
HashSet 底层基于 HashMap 实现,添加对象时执行两步判断:
- 先调用对象的
hashCode()方法,计算哈希值,定位到哈希桶(bucket) - 若桶中已有元素,则逐个调用
equals()方法比对:只有hashCode()相同 且equals()返回 true,才视为重复,拒绝添加
⚠️ 注意:如果只重写 equals() 而不重写 hashCode(),会导致相同逻辑的对象可能被分配到不同桶中,HashSet 无法识别它们相等,从而出现“本该去重却没去重”的错误。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
自定义类必须同时重写 equals 和 hashCode
比如一个 Person 类:
-
equals()要按业务语义定义“相等”:姓名和年龄都相同即为同一人 -
hashCode()必须保证:相等的对象(equals == true)返回相同哈希值;不相等的对象尽量返回不同哈希值(提升性能) - 推荐使用 IDE 自动生成(如 IntelliJ 的
Alt+Insert → equals and hashCode),或用Objects.hash(name, age)
其他 Set 实现的去重方式差异
不同 Set 子类利用 Object 方法的方式略有不同:
-
LinkedHashSet:同样依赖
hashCode + equals,但额外维护插入顺序,适合需要去重又保留顺序的场景 -
TreeSet:不依赖
hashCode和equals,而是要求对象实现Comparable接口(或传入Comparator),通过compareTo()判断大小与唯一性;此时即使equals()返回true,只要compareTo() == 0就算重复
List 去重需手动借助 Set 或 Stream
List 本身允许重复,要实现去重需主动转换:
- 用
new ArrayList(new LinkedHashSet(list)):高效、保持原顺序 - 用
list.stream().distinct().collect(Collectors.toList()):语义清晰,distinct()内部仍调用equals()判断 - 手写循环 +
contains():效率低(每次contains都遍历并调用equals),仅适用于小数据量
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










