hashmap采用高低位异或(h ^ (h >>> 16))是为了将高位信息混合入低位,解决因(n−1)&hash仅用低几位导致的哈希冲突问题;该操作利用异或的敏感性、无溢出和高效性,使索引分布更均匀,且null键统一返回0,确保逻辑一致。

HashMap 的高低位异或(h ^ (h >>> 16))不是随便写的,它解决的是哈希值低位信息过载、高位信息被“浪费”的实际问题。
为什么只用低几位会出问题?
数组长度是 2 的幂次(比如 16、32、64),定位桶位置用的是:
index = (n - 1) & hash
当 n = 16 时,n−1 = 15,二进制是 00001111。按位与操作只保留 hash 的低 4 位,高位再怎么变,对索引毫无影响。
如果 key 的 hashCode 主要差异在高位(比如对象内存地址、时间戳高位等),而低 4 位又很接近(例如多个字符串的 hashCode 低字节相似),就会大量挤进同一桶——哈希冲突陡增。
高位异或如何让分布更均匀?
把高 16 位右移后和低 16 位异或,相当于把高位特征“混合”进低位:
- 原始 hash 是
0x75ab00d2(十进制约 1977393362) - 右移 16 位得
0x000075ab - 异或结果为
0x75ab75ab—— 此时低 16 位已携带原高位信息 - 再和
15 (0b1111)做 & 运算,实际参与计算的低 4 位,就不再只是原始低 4 位,而是融合了高位扰动后的结果
这不是“加法”,而是位运算的精巧平衡
异或(^)有三个关键特性被充分利用:
- 可逆性弱(不追求还原,只求打散)
- 对输入微小变化敏感(一个 bit 改变,输出一半 bit 可能翻转)
- 无进位、无溢出,计算极快,适合高频调用
相比乘法或加法扰动,异或开销最小,且能有效避免因低位重复导致的聚集现象。
null 键也纳入统一逻辑
源码中对 null 键直接返回 0:
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
这保证了 null 总落在 index=0 的桶里,既符合语义(唯一 null 键),又不破坏整体扰动逻辑的一致性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











