hashset去重依赖hashcode和equals协同工作:先用hashcode定位桶(粗筛),再用equals确认是否重复(精判);二者缺一不可,且若equals为true则hashcode必须相同。

HashSet 能自动去重,靠的不是魔法,而是 hashCode 和 equals 协同工作的确定性逻辑。理解它,关键不是背规则,而是看清“先粗筛、再精判”这个两步流程。
HashSet 底层其实是 HashMap 的“简化版”
HashSet 本身不存数据,它把所有元素都作为 key 存进一个内部的 HashMap(value 固定为一个空对象)。所以 HashSet 的去重,本质上就是 HashMap 对 key 的去重逻辑。
这意味着:只要搞懂 HashMap 怎么判断两个 key 是否重复,就等于搞懂了 HashSet。
去重分两步:先用 hashCode 定位“桶”,再用 equals 确认“是不是同一个”
HashMap 内部是一个数组 + 链表/红黑树的结构。当你要 put 一个元素时:
- 第一步:调用该元素的 hashCode(),算出一个整数;
- 第二步:用这个整数对数组长度取模,快速定位到数组中的某个下标位置(即“桶”);
- 第三步:如果这个桶里已经有元素,就逐个调用 equals() 去比对——只有和已有元素 equals 返回 true,才认为是重复,不再插入。
这就像快递柜:先看取件码前两位(hashCode)决定去哪一排柜子,再输入完整取件码(equals)确认是不是你的那件。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
为什么不能只用其中一个?
只靠 hashCode 不行,因为不同对象可能算出相同哈希值(哈希冲突)。例如:
"Aa".hashCode() == "BB".hashCode() // true只靠 equals 也不行,因为每次插入都要和所有已有元素挨个比较,1000 个元素就要比 1000 次,性能直接掉到 O(n)。
两者缺一不可:hashCode 提速,equals 保准。
重写时必须遵守的硬约束
如果你自定义类要放进 HashSet,就必须同时重写这两个方法,并且保证:
- 如果 a.equals(b) == true,那么 a.hashCode() == b.hashCode() 必须成立;
- 反之不成立——hashCode 相同,不意味着 equals 就为 true;
- 对象状态没变时,多次调用 hashCode() 必须返回同一个值。
违反第一条,比如两个逻辑相等的对象 hashCode 不同,HashSet 就会把它们当成完全不同的元素塞进两个桶,导致本该去重的却重复了。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










