必须同时重写hashcode()和equals(),因为hashmap先用hashcode()定位桶,再用equals()比对桶内元素;只重写其一会导致哈希冲突误判或key无法查找。

要用自定义对象作为 HashMap 的 key,必须同时重写 hashCode() 和 equals() 方法,否则会出现“找不到 key”或重复插入等问题。
为什么必须重写这两个方法?
HashMap 查找 key 时,先用 hashCode() 定位到桶(bucket),再用 equals() 在该桶中逐个比对。如果只重写其中一个:
- 只重写
hashCode():不同对象可能返回相同哈希值,但equals()返回false,导致误判为不同 key,实际应视为相同; - 只重写
equals():对象逻辑相等,但哈希值不同,会被散列到不同桶里,get()永远找不到它。
如何正确重写 hashCode()?
确保逻辑上相等的对象(equals() 返回 true)必须有相同哈希值。常用写法是基于参与 equals() 判断的字段计算:
// 示例:Person 类
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
@Override
public int hashCode() {
return Objects.hash(name, age, id);
}
或者手动组合(推荐用 Objects.hash(),简洁且空安全):
- 避免使用随机数、时间戳、数据库 ID 等可变值;
- 不包含可变字段(如未被
final修饰且后续会修改的属性); - 字段顺序和
equals()中的判断顺序保持一致。
如何正确重写 equals()?
遵循对称性、传递性、一致性、非空性、自反性五条原则。标准模板如下:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name) &&
Objects.equals(id, person.id);
}
- 第一行检查引用相等(性能优化);
- 第二行检查 null 和类型(防止 ClassCastException);
- 字段比较用
Objects.equals(),自动处理 null; - 所有用于
equals()的字段,也必须参与hashCode()计算。
额外建议
让 key 对象尽量不可变(immutable):
- 关键字段声明为
final; - 不提供修改这些字段的 setter 方法;
- 若必须可变,请确保在 key 存入
HashMap后不再修改参与 hash 计算的字段,否则 map 行为不可预测。
IDE(如 IntelliJ IDEA 或 Eclipse)可自动生成合规的 hashCode() 和 equals(),推荐使用,但需确认生成逻辑覆盖了全部业务相关字段。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










