Java中 HashMap 的 `hash()` 扰动函数具体做了什么位运算为什么要右移 16 位

雨磊姑娘_3569

雨磊姑娘_3569

2026-10-16

477人浏览

原创

hashmap的hash()方法核心是将key的hashcode高16位无符号右移后与低16位异或,使高位信息参与索引计算,减少哈希冲突;源码为(h = key.hashcode()) ^ (h >>> 16),异或运算确保变化敏感、散列均匀。

java中 hashmap 的 `hash()` 扰动函数具体做了什么位运算为什么要右移 16 位

Java 中 HashMap 的 hash() 方法(也叫“扰动函数”)核心就做了一件事:把 key 的原始 hashCode 高 16 位“混入”低 16 位,再通过异或保留双方变化特征。它不是为了加密或隐藏,而是为了让低位索引计算时也能反映高位差异,从而减少哈希冲突。

具体做了什么位运算

源码实现非常简洁:

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

这行代码包含两个关键操作:

  • 无符号右移 16 位(h >>> 16):把原始 32 位 int 的高 16 位移到低 16 位位置,高位补 0。例如:
    原始 h = 0x1234ABCD(二进制高16位是 0001001000110100),
    右移后变成 0x00001234(即 00000000000000000001001000110100)。
  • 与原值异或(^):将 h 和 h >>> 16 按位异或。相同为 0,不同为 1,不进位、不丢信息。结果的低 16 位是“原低16位 ⊕ 原高16位”,高 16 位基本保留原高16位(但受异或影响略有变化)。

为什么偏偏是右移 16 位

因为 int 是 32 位,16 是它的一半。这个设计不是随意选的,而是兼顾了效率和效果:

  • 数组长度始终是 2 的幂(如 16、32、64…),所以真正参与下标计算的只有 hash 值的低若干位(比如长度 16 → 只用低 4 位;长度 1024 → 用低 10 位)。
  • 如果直接用原始 hashCode,而它的高 16 位经常变化(比如对象内存地址、时间戳等生成的 hash),但低几位几乎不变,那所有这些 key 就会落到同一个桶里——高位变了,索引却没变,冲突激增。
  • 右移 16 位后异或,等于把高 16 位“折叠”进低 16 位。这样即使原始 hash 仅高位不同,扰动后的低 16 位也会明显不同,最终算出的数组下标更分散。
  • 选 16 而非 8 或 24,是因为它能最大程度覆盖低位区域,又避免过度扰动导致规律性反而下降;实测表明 16 位在各类数据分布下冲突率最低。

为什么不选 & 或 | 运算

异或(^)是唯一适合“混合+敏感响应”的位运算:

  • &(与):结果偏向 0。只要某一位是 0,结果就是 0 —— 高位变化可能完全被掩盖。
  • |(或):结果偏向 1。只要某一位是 1,结果就是 1 —— 容易让不同 key 算出相同低 16 位。
  • ^(异或):0⊕0=0,1⊕1=0,0⊕1=1,1⊕0=1。任意一位变化,结果位必然翻转。高位或低位哪怕只差 1bit,扰动后低 16 位大概率整体不同,对变化最敏感,散列质量最高。

扰动后怎么定位数组下标

扰动只是第一步,真正决定存到哪的是:

int index = (table.length - 1) & hash;

因为 table.length 总是 2 的幂,所以 length - 1 的二进制全是 1(如 16−1=15 → 1111)。& 运算等价于取 hash 的低 log₂(length) 位,比 % 快得多。而扰动确保了这几位不只是原始 hash 的“死板低位”,而是融合了高位信息的“活”低位。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

10497

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

7622

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6652

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1144

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

928

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1376

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2769

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20071

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1215

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习