HashSet判断元素重复靠hashCode()定位桶+equals()桶内比对;自定义类须重写二者,否则内容相同的对象被视为不同;add()返回false表明重复。

HashSet 判断元素是否重复,靠的是两步配合:先用 hashCode() 快速分流定位,再用 equals() 精确比对。不是简单遍历全部元素,而是通过哈希表结构大幅提速。
第一步:用 hashCode() 定位桶位置
添加或查找元素时,HashSet 先调用该元素的 hashCode() 方法,算出一个整数哈希值;再用这个值对底层数组长度取模,确定它该落在哪个“桶”(bucket)里。
- 如果目标桶为空,直接插入,不重复
- 如果桶里已有元素,说明发生了哈希冲突,进入第二步
- 注意:两个对象 hashCode 不同,一定不重复,不会调用 equals()
第二步:在同一个桶里用 equals() 逐个确认
只有当新元素和桶中某个已有元素的 hashCode() 相同,才会触发 equals() 比较:
- 如果
equals()返回 true,视为重复,添加失败(add()返回false) - 如果所有比较都返回 false,说明是不同元素,允许插入
- 这个过程只发生在同一个桶内,范围小、效率高
为什么自定义类必须重写 hashCode 和 equals
Java 默认的 Object.hashCode() 返回内存地址,Object.equals() 比较引用——导致两个内容相同的新对象也被当成不同元素:
- 不重写 → 每次 new 出来的 Person 都有不同哈希值,equals 也返回 false → HashSet 会存多份
- 正确做法:只要业务上认为“姓名+年龄相同即为同一人”,就要让这两个字段参与
hashCode()计算,并在equals()中按同样逻辑判断 - String、Integer 等 JDK 类已内置合理实现,可直接使用
怎么验证是否重复
最直接的方式是看 add() 的返回值:
-
set.add(obj)返回 true → 元素不存在,已成功加入 - 返回 false → 元素已存在(hashCode + equals 全部匹配),未添加
- 也可以用
set.contains(obj),内部执行同样的两步判断逻辑











