必须同时重写equals()和hashCode()方法,否则违反Java规范契约,导致HashMap、HashSet等哈希集合行为异常,如重复插入、查找失败等。

因为 Java 规范明确要求:如果两个对象通过 equals() 判定相等,它们的 hashCode() 必须返回相同值。否则,对象在哈希集合中会行为异常。
哈希结构依赖 hashCode 定位
HashMap、HashSet 等容器内部是“数组 + 链表/红黑树”的结构。插入或查找时,先用 hashCode() 计算索引位置(桶号),再在该桶内用 equals() 做精确比对。
- 若只重写
equals(),未重写hashCode(),则默认使用 Object 的实现——基于内存地址生成哈希值 - 两个内容相同但不同实例的对象(如
new Person("Alice", 25)和new Person("Alice", 25)),equals()返回true,但hashCode()很可能不同 - 结果:它们被散列到不同桶中,
contains()、get()等操作直接失败,查不到本应存在的对象
违反契约会导致集合失效
HashSet 依靠 hashCode() + equals() 共同保证元素唯一性;HashMap 依靠二者共同保证键的准确映射。不一致时:
- 同一个逻辑对象可能被重复加入
HashSet(因哈希值不同,系统认为是新元素) - 用相等的 key 调用
map.get(key)返回null(因去错了桶,没机会触发equals()) - 哪怕手动调用
equals()结果为true,集合本身已无法识别这种相等关系
重写必须保持计算逻辑一致
hashCode() 的实现不能随意,它必须和 equals() 中用于判断相等的字段完全对应:
- 如果
equals()比较的是name和age,那hashCode()就只能基于这两个字段计算(例如用Objects.hash(name, age)) - 若
hashCode()多用了某个未参与equals()判断的字段(比如id),就可能出现:两个对象equals()为true,但hashCode()不同 - 反之,若
hashCode()漏掉某个参与equals()的字段,会导致大量哈希冲突,性能下降
不是“建议”,而是契约强制要求
这不是最佳实践或风格问题,而是 Java Object 类文档中白纸黑字的契约(contract):
- “If two objects are equal according to the
equals(Object)method, then calling thehashCode()method on each of the two objects must produce the same integer result.” - 所有标准集合类(
HashMap、HashSet、ConcurrentHashMap等)都严格依赖此契约运行 - IDE(如 IntelliJ)和静态检查工具(如 SonarQube)会直接报错或警告:重写了
equals()却未重写hashCode()


















