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

6.HashMap 从 JDK7 到 JDK21 的演进

HashMap 从 JDK7 到 JDK21 的演进(含红黑树化机制)

🚀 高频指数:★★★★★
🎯 你将收获:底层结构演变、扩容与树化机制、hash冲突解决、并发风险与源码逻辑图。


一、为什么 HashMap 面试永远问不完?

因为它融合了:

  • 数组、链表、红黑树三种数据结构;
  • 哈希算法、扩容逻辑、并发原理;
  • JVM 内存布局与 GC 行为。

☕️ 一句话总结:“一个 HashMap = 一部 Java 底层史。”


二、结构总览:数组 + 链表 + 红黑树

组成部分说明
Node<K,V>[] table主数组(哈希桶)
Node<K,V>.next冲突时形成链表
TreeNode<K,V>冲突过多时转为红黑树
threshold扩容阈值(容量 × 负载因子)
loadFactor默认0.75,平衡空间与查找效率

三、hash 冲突与扰动函数

1️⃣ key → hash

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

🔹 高16位与低16位异或,减少碰撞。
🔹 确保高位参与寻址,分布更均匀。

2️⃣ 取模定位桶

int index = (n - 1) & hash;

✅ 位运算代替 %,提升性能。
例如容量16 → (16-1)=15 → 按位与实现快速取模。


四、JDK7 与 JDK8 的重大差异

特性JDK7JDK8
存储结构数组 + 链表数组 + 链表 + 红黑树
插入方式头插法(链表逆序)尾插法(链表顺序)
扩容实现重新计算每个元素位置利用 hash 位优化分配
初始化时机延迟到第一次 put同样延迟
遍历顺序不保证顺序同样不保证
并发问题存在死循环风险已解决(尾插+安全迁移)

☕️ 口诀:“七头八尾,八树化。”


五、核心源码解析(JDK8)

1️⃣ put 流程简图

hash → 定位桶 → 无元素则新建Node→ 有元素则:- key相同 → 覆盖value- key不同 → 链表/树追加节点- 链表长度≥8 → 树化- size > threshold → 扩容

2️⃣ treeifyBin 核心逻辑

if (tab == null || (n = tab.length) < 64)resize(); // 数组太小先扩容
elsetab[i] = new TreeNode<>(...); // 链表转红黑树

树化条件:

  • 链表长度 ≥ 8;
  • 且数组容量 ≥ 64;
    否则优先扩容而非树化。

六、扩容机制详解

扩容阈值计算

threshold = oldCapacity * loadFactor;

resize() 方法逻辑

newCap = oldCap << 1;  // ×2 扩容
for (Node<K,V> e : oldTab) {if (e.hash & oldCap == 0)newTab[j] = e;        // 留在原桶elsenewTab[j + oldCap] = e; // 移至新桶
}

⚙️ 利用 hash 位的“高1/低0”判断是否迁移 → 无需重新计算 hash。

📌 口诀:“低位留原,高位加偏。”


七、红黑树化机制(JDK8+)

链表节点超过8时树化(TreeNode 结构):

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {TreeNode<K,V> parent, left, right, prev;boolean red;
}
  • 插入、删除后会自动旋转、着色;
  • 当桶中元素数量 < 6 时退化为链表。

✅ 树化提升最差复杂度从 O(n) → O(log n)。


八、hashCode、equals、冲突与覆盖

put() 时判断 key 相等逻辑:

if (p.hash == hash && (p.key == key || key.equals(p.key))) {p.value = newValue; // 覆盖
}

所以必须保证:equals 与 hashCode 一致性


九、JDK21 中 HashMap 的变化

🆕 自 JDK19 起,HashMap 内部已针对高性能场景做进一步优化。

版本优化内容
JDK19增加随机种子 hash,防御哈希碰撞攻击
JDK20改进 resize 逻辑,减少复制开销
JDK21支持“Compact HashMap”实验性特性(部分场景内存优化)
JDK21+新增 computeIfAbsent 等 Lambda 优化内联

☕️ 趋势:从“稳定结构”向“高并发与内存友好”方向演进。


十、面试官追问清单

面试问题答题要点
HashMap 初始容量?默认16,负载因子0.75
扩容时机?size > capacity × loadFactor
链表树化条件?链表长度≥8且容量≥64
为什么用红黑树?保证查找O(log n),避免退化
JDK7 与 JDK8 最大区别?链表头插→尾插 + 树化机制
并发风险?JDK7 多线程扩容死循环,JDK8已改进但仍非线程安全

十一、项目实践建议

场景建议
数据量已知new HashMap<>(expectedSize * 4 / 3) 避免扩容
多线程环境使用 ConcurrentHashMap
Key 为自定义类必须重写 equals 与 hashCode
高性能缓存调整负载因子到0.6–0.7 平衡空间与效率

十二、口诀记忆

☕️ “数组为体,链表为骨,红黑为盾,扩容自愈。”

补充版:
“七头八尾八树化,六退回链六十四。”


十三、小结

知识点要点
数据结构数组 + 链表 + 红黑树
默认参数初始容量16,负载因子0.75
扩容策略×2扩容,重新分配桶
树化规则链表≥8且容量≥64
性能复杂度O(1) → O(log n)(树化后)
并发安全非线程安全(推荐ConcurrentHashMap)

✅ 一句话总结:“HashMap 一半是算法,一半是艺术。”

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

相关文章:

  • 网站上传模板后asp.net网站开发项目源码
  • 网站建设与维护选择题建设展示型网站公司哪家好
  • python_相比C++的优点、改进和适用场景
  • 网站建设指导思想c++可视化界面设计
  • 商务网站信息审核的重要性在于电商平台的营销方式
  • 卡盟做网站芜湖企业网站制作
  • 网站 维护做爰全过程的视频网站
  • 阳泉网站建设移动互联网技术体系架构示意图
  • 美团做团购网站如何网站建设自己怎么个人网站
  • Twine/Harlowe 网页对话式作品开发技术手册
  • 怎样让自己的网站被收录博客网站是自己做的吗
  • 用jsp做网站的技术路线英文网站建站山东
  • 店铺装修网站免费建立网站软件
  • php网站出现乱码app推广拉新一手渠道
  • 电气工程师求职问答-中级篇
  • 个人博客网站备案吗最简单的网站怎么做
  • 织梦更新网站地图画网站 模板
  • 个人网站 做外贸wordpress安卓显示
  • 峰值保持电路与峰值提取算法实现放射性核脉冲信号峰值提取
  • 内网网站搭建设推销什么企业做网站和app
  • 开源展示型网站莱芜百度贴吧
  • 做网站要注意的wordpress找回密碼
  • 东莞网站建设 光龙做网站备案哪些条件
  • 维护网站建设空间出租怎么生成链接
  • 搜狗推广做网站要钱吗手机网站怎么搜索引擎
  • 第5天python内容
  • 网站建设进展报告做excel的网站
  • 怎样做付费下载的网站wordpress 引用 插件
  • 连云港市建设银行网站wordpress排除首页显示
  • 内江市规划建设教育培训中心网站wordpress 微信公众