必须重写 hashcode,因为哈希集合要求 equals 相等的对象 hashcode 必须相同;否则会导致存入后查不到、set 重复添加等问题;正确做法是确保 equals 和 hashcode 基于相同字段计算,并满足契约约束。

重写 equals 就必须重写 hashCode,根本原因不是语法强制,而是为了遵守 Java 对哈希集合(如 HashMap、HashSet)的契约要求:如果两个对象逻辑上相等(equals 返回 true),它们的 hashCode 值必须相同。
为什么哈希集合依赖这两个方法协同工作?
哈希集合底层靠“分桶”提升性能:先用 hashCode 算出对象该进哪个桶,再在桶内用 equals 精确比对。
- 如果只重写
equals,不重写hashCode,内容相同的两个对象可能被分配到不同桶里——get()或contains()时根本不会去那个桶找,直接返回null或false; - 结果就是:存进去了,却查不到;或本该去重的元素,重复添加进
Set。
不重写会出什么具体问题?
举个典型例子:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 定义
Person类,只重写了equals(按 name 和 age 判等),但没动hashCode; -
Person p1 = new Person("Alice", 25);和Person p2 = new Person("Alice", 25);调用p1.equals(p2)返回true; - 但
p1.hashCode() != p2.hashCode()(因默认基于内存地址); - 把
p1放进HashSet,再用p2查找或添加,Set会认为它是新对象,导致重复; - 同理,
Map.put(p1, "info")后,map.get(p2)返回null。
怎么写才算“正确重写”?
核心是保持一致性,且符合通用原则:
-
equals必须满足自反性、对称性、传递性、一致性、非空性; -
hashCode必须保证:只要equals比较所用的字段没变,多次调用返回值就一致; - 如果
a.equals(b)为true,则a.hashCode() == b.hashCode()必须成立; - 推荐用
Objects.hash(field1, field2, ...)生成hashCode,它自动处理null并复用标准算法; - IDE(如 IntelliJ)可一键生成,但要确认参与比较的字段与
hashCode计算字段完全一致。
什么情况下可以不重写 hashCode?
如果你的类**永远不会作为哈希集合的 key 或元素**(比如纯内部 DTO、只用于日志打印、或只存在 List/Array 中),那 hashCode 是否重写不影响功能。但这种“侥幸”不建议,因为业务演进后容易埋坑,统一重写更稳妥。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










