必须同时重写equals()和hashCode()方法,否则哈希集合(如HashMap、HashSet)会出现查不到、存重复、删不掉等异常行为,因哈希结构依赖hashCode()定位桶、再用equals()精确匹配。

因为 Java 规范强制要求:如果两个对象 逻辑相等(即 equals() 返回 true),它们的 hashCode() 值必须相同。否则,对象在 HashMap、HashSet 等哈希集合中会行为异常——比如查不到、存重复、删不掉。
核心原因:哈希集合依赖两步定位
哈希结构(如 HashMap)不是靠 equals() 逐个比对,而是先用 hashCode() 快速算出“桶位置”,再在该桶内用 equals() 精确匹配。
- 若只重写
equals(),没重写hashCode(),则默认使用Object.hashCode()(通常基于内存地址) - 两个内容相同但不同实例的对象(如
new Person("张三", 25)和new Person("张三", 25)),equals()返回true,但hashCode()很可能不同 - 结果:它们被散列到不同桶里 →
HashSet认为是两个不同元素 → 允许重复;HashMap无法用等价 key 查到已存的 value
违反约定的实际后果
看似只是“少写一个方法”,但会直接破坏集合语义:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
HashSet.add(p1); set.contains(p2)返回false,即使p1.equals(p2)为true - 同一个对象两次
put到HashMap,可能生成两条键值对(因哈希位置不同) - 对象加入
HashSet后,若其参与hashCode计算的字段被修改(且未重新add),将永远无法被remove或contains
怎么写才安全
只要保证两点:逻辑相等 ⇒ 哈希值相等;字段不变 ⇒ 哈希值不变。
立即学习“Java免费学习笔记(深入)”;
- 用相同字段参与
equals()和hashCode()计算(如都用name和age) - 推荐用
Objects.hash(name, age),自动处理null,简洁可靠 - 避免在
hashCode()中使用可变字段(如后期会通过 setter 修改的属性) - 若类是可变的,且字段可能变化,应明确文档说明:修改后需从集合中移除再重新添加
这不是“建议”,而是契约
equals() 和 hashCode() 是 Java 对象契约的一部分,写在 Object 类的 Javadoc 里。IDE(如 IntelliJ)甚至会在你重写 equals() 时主动提示“Generate hashCode()”。不遵守,不是风格问题,是潜在 bug 的根源。

















