hashset判断重复需先调用hashcode()定位桶,再用equals()逐个比较;二者必须同时重写且保持一致,否则去重失效或性能下降。

HashSet 存储不重复的自定义对象,关键不在“往里加”,而在“怎么判断重复”——它靠的是你写的 hashCode() 和 equals() 方法。默认情况下,这两个方法来自 Object 类,只比较内存地址,所以哪怕两个对象内容完全一样,HashSet 也认为是不同的元素。
为什么重写 hashCode 和 equals 是必须的
HashSet 判断是否重复分两步:
- 先算对象的
hashCode()值,决定存到哈希表哪个“桶”里; - 如果桶里已有元素,再调用
equals()逐个比对,确认是否真相同。
如果只重写 equals() 不重写 hashCode(),相同对象可能被分到不同桶里,equals() 根本不会被调用;如果只重写 hashCode() 不重写 equals(),所有对象哈希值一样,全挤在一个桶里,效率暴跌且仍无法去重。二者必须配套。
怎么正确重写这两个方法
推荐用 IDE 自动生成(如 IntelliJ 或 Eclipse:Alt + Insert → “Generate hashCode() and equals()”),选中参与比较的字段(比如 name 和 age)。生成的代码逻辑清晰、覆盖 null 安全和类型检查。
示例(Person 类):
-
hashCode():通常用Objects.hash(name, age),简洁可靠; -
equals():先判空、判类型、判引用,再逐字段比较,用Objects.equals(name, other.name)处理 null。
验证是否生效的小技巧
写个简单测试:创建两个内容完全相同的对象(如 new Person("张三", 25) 两次),add 进 HashSet 后打印 size。如果 size 是 1,说明去重成功;如果是 2,说明重写没起作用——回头检查方法是否加了 @Override、字段是否选对、有没有拼写错误。
其他注意事项
- 字段一旦参与了
hashCode()和equals(),就尽量别改。如果对象加入 HashSet 后修改了这些字段,可能导致无法 remove 或 contains 失败; - 如果业务上“唯一性”由 ID 决定,就只把
id字段放进生成逻辑里; - TreeSet 不依赖这两个方法,而是依赖
Comparable或Comparator,但那是另一条路。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











