目录
在 Java 中,hashCode() 是 Object 类定义的一个方法(所有类都间接继承自 Object),它返回一个 int 类型的哈希码值(哈希值)。这个值本质是对象的一种 “数字指纹”,由对象的内部信息(如属性值)计算得出,核心作用是辅助哈希机制(如 HashMap、HashSet)实现高效的存储和查询。
一、hashCode 的核心作用
hashCode() 的设计初衷是为了快速定位对象在哈希表中的位置,减少 “对象是否存在” 的判断成本。
举个例子:在 HashSet 中判断 “是否包含某个对象” 时,若直接用 equals() 逐个比较集合中的所有对象,时间复杂度是 O(n)(效率低);而借助 hashCode() 可以先通过哈希值定位到对象可能存在的 “小范围区域”(如 HashMap 的桶),再在该区域内用 equals() 精确比较,时间复杂度可优化到 O(1)(平均)。
二、hashCode 与 equals 的强制规范
Java 语言规范对 hashCode() 和 equals() 有严格的约束,这是保证哈希集合(如 HashMap)正确工作的前提:
-
若两个对象
equals(Object o)返回true,则它们的hashCode()必须返回相同的值。(原因:如果两个对象 “相等”,哈希机制必须将它们视为同一个对象,否则会在哈希表中存储重复数据。) -
若两个对象
hashCode()返回相同的值,它们的equals(Object o)不一定返回true。(这是哈希冲突:不同对象可能计算出相同的哈希值,此时需要用equals()进一步区分。)
三、hashCode 的计算逻辑
hashCode() 的具体计算方式由类自行定义(可重写),核心原则是:相同属性的对象应返回相同的哈希值,不同属性的对象应尽量返回不同的哈希值(减少冲突)。
1. 默认实现(Object 类)
Object 类的 hashCode() 是 native 方法(底层由 C++ 实现),通常返回对象的内存地址的哈希映射值(不同对象的内存地址不同,因此哈希值也不同)。
2. 常见类的重写实现
-
String 类:根据字符序列计算哈希值,相同字符序列的字符串哈希值一定相同:
java
运行
public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; // 31是质数,减少哈希冲突 } hash = h; } return h; }例:
"abc".hashCode()与"abc".hashCode()结果相同,"abc"与"abd"结果不同。 -
自定义类:通常根据关键属性重写
hashCode(),确保 “属性相同的对象哈希值相同”。例如:java
运行
class Student { private String id; private String name; // 仅根据id计算哈希值(id相同则视为同一学生) @Override public int hashCode() { return id.hashCode(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return id.equals(student.id); // 与hashCode逻辑一致 } }
四、为什么重写 equals 必须重写 hashCode?
如果只重写 equals() 而不重写 hashCode(),会违反 Java 规范的第一条(相等的对象哈希值必须相同),导致哈希集合工作异常。
例如:两个 Student 对象 s1 和 s2 的 id 相同(s1.equals(s2) = true),但未重写 hashCode() 时,它们的哈希值默认是内存地址的映射(可能不同)。此时将它们放入 HashSet 中,HashSet 会认为它们是不同对象,导致重复存储(违背 Set 不重复的特性)。
总结
hashCode() 是对象的 “数字指纹”,核心作用是辅助哈希机制快速定位对象,与 equals() 配合保证哈希集合的正确性和效率。其关键规范是:相等的对象必须有相同的哈希值,哈希值相同的对象不一定相等。在自定义类中,若重写 equals(),必须同时重写 hashCode(),且两者逻辑保持一致(基于相同的属性计算)。

被折叠的 条评论
为什么被折叠?



