当前位置: 首页 > news >正文

解剖HashMap的put流程 <一> (JDK 1.8)

HashMap 的put流程中,为什么第一步是计算 Key 的哈希值?本文从 "是什么"、"解决什么问题" 和 "如何计算" 三个维度来理解。


具体来说,put方法的大致流程是:

因此,计算哈希值是整个流程的起点,没有哈希值就无法确定元素应该存在哪里

二、计算哈希值能解决什么问题?

核心解决 "如何将任意类型的 Key 高效映射到固定范围的数组索引" 的问题,具体体现在:

  1. 实现快速定位
    数组的优势是 "随机访问"(通过索引直接定位元素,时间 O (1)),但数组索引是整数且范围固定(0~n-1)。哈希值通过计算能将任意类型的 Key(如 String、自定义对象等)转换为整数,再进一步映射到数组索引,从而利用数组的高效访问特性。

  2. 减少哈希冲突概率:链接:什么是哈希冲突
    好的哈希计算能让不同的 Key 尽量生成不同的哈希值,从而均匀分布到数组的不同位置,避免大量元素集中在同一个索引(减少链表 / 红黑树的长度),保证操作效率。

  3. 适配数组容量
    哈希值经过处理后能被限制在数组容量范围内(如通过hash & (n-1)计算索引),确保元素不会存储到数组之外。

三、哈希值的计算过程(JDK 1.8)

HashMap 对 Key 的哈希值计算分为三步,层层优化以保证分布均匀性:

1. 调用 Key 的hashCode()方法

每个对象(包括自定义对象)都继承了Object类的hashCode()方法,返回一个 32 位整数。

  • 例如:"abc".hashCode()的结果是96354Integer.valueOf(100).hashCode()的结果是100
  • 作用:将任意类型的 Key 转换为一个整数(哈希值的基础)。
2. 扰动函数(二次哈希)

直接使用hashCode()的结果可能导致 "高位特征被忽略"(因为数组容量通常较小,如初始 16,计算索引时只会用到哈希值的低几位)。因此 JDK 1.8 通过扰动函数混合高位和低位:

static final int hash(Object key) {int h;// key为null时哈希值为0;否则将hashCode与自身右移16位的结果异或return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
  • 原理:将哈希值的高 16 位与低 16 位进行异或(^),让高位的特征 "混入" 低位,增加哈希值的随机性。
  • 例:若hashCode()结果为0x12345678,右移 16 位后为0x00001234,异或后得到0x1234444c,高低位特征均被保留。
3. 计算数组索引

通过位运算将扰动后的哈希值映射到数组容量范围内:

// n为数组容量(必须是2的幂,如16、32等)
int index = hash & (n - 1);

  • 等价于hash % n(取模运算),但位运算&效率更高。
  • 例:当容量n=16时,n-1=15(二进制1111),任意哈希值与15&运算,结果一定在0~15之间(符合数组索引范围)。

最后归纳

  • 第一步是计算哈希值:这是 HashMap 将 Key 映射到数组索引的基础,是实现高效存取的前提。
  • 解决的核心问题:将任意类型 Key 转换为可用于数组索引的整数,同时通过优化分布减少冲突,保证效率。
  • 计算逻辑hashCode() → 扰动函数(混合高低位) → 位运算(hash & (n-1))→ 得到索引。

这种设计既利用了数组的快速访问特性,又通过哈希优化平衡了时间和空间效率,是 HashMap 高性能的关键。

http://www.dtcms.com/a/331713.html

相关文章:

  • 22.Linux samba服务
  • USB 3.0 link command 定义
  • 知识的本质
  • 数域筛法GNFS---C语言实现
  • 20道CSS相关前端面试题及答案
  • Elasticsearch:如何使用 Qwen3 来做向量搜索
  • css中container和media的用法和区别
  • SRWare Iron:隐私保护与高效浏览的完美结合
  • C++ mutex的实现源码分析
  • Xsens动作捕捉与AI驱动人形机器人训练革新
  • WVP和ZLM部署与接入NVR指南环境准备
  • 【React】hooks 中的闭包陷阱
  • 三轴云台之脉宽调制技术篇
  • Qt基本槽
  • 链游(GameFi)开发破局:如何平衡可玩性与经济模型可持续性?
  • GraphRAG:AI理解复杂知识的未知领域,开启探索之旅
  • 《Python函数:从入门到精通,一文掌握函数编程精髓》
  • MySQL主从原理
  • Linux 文件系统简介
  • 解析 TrueType/OpenType 格式的可变字体(Variable Font),提取其所有命名实例(Named Instances) 的名称信息
  • ESP32S3的LVGL配置参数解释、动画播放优化(更新中)
  • 4.1vue3的setup()
  • 《WebGL中FBO的底层运行逻辑》
  • 编程与数学 02-017 Python 面向对象编程 01课题、面向对象
  • 【会员专享数据】2000-2024年我国乡镇的逐日PM₁₀数据(Shp/Excel格式)
  • linux初始化配置
  • 计算机网络知识
  • 基于Java飞算AI的Spring Boot聊天室系统全流程实战
  • 【奔跑吧!Linux 内核(第二版)】第6章:简单的字符设备驱动(三)
  • CMake include_directories()使用指南