扰动函数的核心作用是将hashCode高16位异或到低16位,使高位信息参与索引计算,提升低位随机性、降低哈希碰撞;其实现为(h = key.hashCode()) ^ (h >>> 16),仅适用于非null键,null键固定映射到table[0]。

HashMap 的扰动函数通过重新分布哈希值的位信息,让高位参与索引计算,从而提升哈希值的离散度,降低桶冲突概率。
扰动函数的核心作用是“打散高位”
Java 中 key 的 hashCode() 返回的是 32 位整数,但 HashMap 实际容量通常是 2 的幂次(如 16、32、64),计算数组下标用的是 (n - 1) & hash。由于 n-1 的二进制低位全为 1,该运算只取 hash 的低几位——高位变化完全被忽略。如果多个 key 仅高位不同、低位相同,就会映射到同一桶,造成碰撞。
扰动函数让高位“下沉”参与低位运算,把原本被丢弃的高位特征利用起来,使相似 hash 值更可能产生差异化的索引。
具体实现:h = h ^ (h >>> 16)
这是 JDK 7/8 中的标准扰动逻辑:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 将原始 hash 值无符号右移 16 位(即取高 16 位)
- 再与原 hash 异或(^),实现高低位混合
- 异或操作保持可逆性且计算极快,无性能负担
- 例如:hash = 0xABCDEF01,右移后为 0x0000ABCD,异或得 0xABCD22C0 —— 原高位 ABCD 已影响低位结果
为什么这样能减少碰撞
未扰动时,像 "Aa" 和 "BB" 这类字符串在某些 JDK 版本中 hashCode 恰好只差在高 16 位,低位完全一致,导致索引相同;扰动后它们的低位被高位改变,大概率分到不同桶。
本质是提升 hash 值对低位的敏感度,让原本聚集在少数桶里的 key 更均匀地铺开,尤其在初始容量小、key 集合存在规律性时效果明显。
注意:扰动不是万能的
它不能解决所有哈希冲突,比如:
- 相同 key 的 hashCode 固定,扰动后仍相同 → 必然同桶(这是正确行为)
- 极端情况下,两个不同 hash 经扰动后仍碰撞 → 后续靠链表或红黑树处理
- 若 key 自身 hashCode 实现质量差(如总返回常量),扰动也无力回天
所以,高质量的 hashCode 实现 + 扰动函数 + 良好扩容机制,三者共同保障 HashMap 性能。

















