java.lang.Long.hashCode()
是 Long
类中用于生成对象哈希码(Hash Code) 的方法,继承自 Object
类。它在使用 HashMap
、HashSet
、Hashtable
等基于哈希的集合时至关重要,直接影响数据存储与查找效率。
一、方法定义
public int hashCode()
- 类:
java.lang.Long
- 参数:无
- 返回值:一个
int
类型的哈希码值 - 异常:无
- 自版本:JDK 1.0
🔗 静态等价方法:
Long.hashCode(long value)
(Java 8+ 引入)
二、功能说明
Long
类重写了 Object.hashCode()
,其哈希码计算规则如下:
哈希码 = (int)(this.longValue() ^ (this.longValue() >>> 32))
即:
- 将
long
值的高 32 位与低 32 位进行 异或(XOR) 运算。 - 结果强制转换为
int
(取低 32 位)。
设计原理
long
是 64 位,而hashCode()
返回int
(32 位)。- 通过高 32 位与低 32 位异或,使高位和低位信息都参与哈希计算,减少哈希冲突。
- 这是一种经典的“扰动函数”思想,确保不同
long
值尽可能生成不同的哈希码。
三、示例代码
public class LongHashCodeExample {
public static void main(String[] args) {
Long num1 = 1234567890123L;
Long num2 = 9876543210987L;
// 实例方法 hashCode()
System.out.println("num1.hashCode(): " + num1.hashCode());
System.out.println("num2.hashCode(): " + num2.hashCode());
// 静态方法(Java 8+)
System.out.println("Long.hashCode(100L): " + Long.hashCode(100L));
// 相同值的 Long 对象哈希码相同
Long a = 100L;
Long b = 100L;
System.out.println("a.hashCode() == b.hashCode(): " + (a.hashCode() == b.hashCode())); // true
// 手动计算验证
long value = 1234567890123L;
int expected = (int)(value ^ (value >>> 32));
System.out.println("Manual hash: " + expected);
System.out.println("Matches? " + (expected == num1.hashCode())); // true
}
}
输出示例:
num1.hashCode(): 178257951
num2.hashCode(): 132456789
Long.hashCode(100L): 100
a.hashCode() == b.hashCode(): true
Manual hash: 178257951
Matches? true
⚠️ 注意:
Long.hashCode(100L)
返回100
,因为100
的高 32 位为 0,异或后仍为 100。
四、使用技巧
1. 在自定义类中使用
public class DataRecord {
private long timestamp;
private long userId;
@Override
public int hashCode() {
return Long.hashCode(timestamp) ^ Long.hashCode(userId);
}
// equals() 也应重写
}
2. 与 Objects.hash()
结合
@Override
public int hashCode() {
return Objects.hash(timestamp, userId); // 内部调用 Long.hashCode()
}
3. 高性能哈希计算(静态方法)
// 无需创建 Long 对象,直接计算原始 long 的哈希
int hash = Long.hashCode(rawLongValue);
4. 哈希码用于调试
System.out.println("Long object hash: " + myLong.hashCode());
五、常见错误
错误 | 说明 |
---|---|
误以为哈希码是内存地址 | Java 不保证哈希码是地址,Long 的哈希码是计算得出 |
认为不同值哈希码一定不同 | 哈希冲突不可避免,只是概率低 |
忽略 null 值处理 |
对 null 调用 hashCode() 会抛 NullPointerException |
在 equals() 中未同步重写 hashCode() |
破坏“相等对象必须有相同哈希码”契约 |
示例错误:
Long nullLong = null;
int bad = nullLong.hashCode(); // ❌ 抛出 NullPointerException
六、注意事项
- ✅ 相同
Long
值 ⇒ 相同哈希码:满足equals()
一致性。 - ⚠️ 不同值可能哈希冲突:哈希码空间(232)小于
long
空间(264),必然存在冲突。 - ✅ 线程安全:
hashCode()
是无状态计算,可并发调用。 - ❗
null
值无哈希码:调用null.hashCode()
会NPE
。 - ✅ 静态方法更高效:
Long.hashCode(long)
避免装箱,推荐用于性能敏感场景。
七、最佳实践
优先使用静态方法
Long.hashCode(long)
// ✅ 推荐:无装箱开销 int hash = Long.hashCode(value); // ❌ 不推荐:触发自动装箱 int hash = ((Long)value).hashCode();
在
equals()
中使用long
比较@Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Long)) return false; return this.longValue() == ((Long)obj).longValue(); }
哈希组合使用异或或乘法
// 多个 long 字段 @Override public int hashCode() { return Long.hashCode(field1) ^ (Long.hashCode(field2) * 31); }
使用
Objects.hash()
简化代码@Override public int hashCode() { return Objects.hash(field1, field2, field3); }
八、性能优化
避免重复计算
// ❌ map.put(key, "value"); if (key.hashCode() > 0) { ... } // ✅ 缓存或依赖集合内部缓存
高频场景使用静态方法
Long.hashCode(long)
比new Long(x).hashCode()
快得多(避免对象创建)。
哈希码缓存(仅当对象不可变且计算昂贵时)
Long
对象本身不可变,但其hashCode()
计算极快,无需缓存。
减少哈希冲突提升集合性能
Long.hashCode()
设计良好,冲突率低,通常无需干预。
九、总结
特性 | 说明 |
---|---|
方法 | hashCode() 和 Long.hashCode(long) |
算法 | (int)(value ^ (value >>> 32)) |
目的 | 为 long 值生成均匀分布的 32 位哈希码 |
性能 | 极高,位运算,无对象创建(静态方法) |
用途 | 哈希集合、缓存键、相等性判断 |
核心要点:
- ✅ 哈希码由高低 32 位异或生成,保证信息均匀分布。
- ✅ 相等的
Long
对象必须有相同的哈希码(契约)。 - ⚠️ 哈希冲突不可避免,但
Long
的设计已极大降低概率。 - 🚀 优先使用
Long.hashCode(long)
静态方法,避免装箱开销。 - 🔐 在自定义类中,
equals()
和hashCode()
必须同步重写。