【Java集合】深入浅出 Java HashMap:从链表到红黑树的“进化”之路

🍂枫言枫语:我是予枫,一名行走在 Java 后端与多模态 AI 交叉路口的研二学生。

“予一人以深耕,观万木之成枫。”

在这里,我记录从底层源码到算法前沿的每一次思考。希望能与你一起,在逻辑的丛林中寻找技术的微光。

在 Java 集合框架中,HashMap的底层实现在 JDK 1.8 迎来了一次重大革新:引入了红黑树。这一设计并非为了酷炫,而是为了解决哈希碰撞导致的性能退化问题。本文将结合底层源码,带你彻底搞懂 HashMap 是在什么条件下、如何进行树化的。


一、 核心源码常量定义

HashMap.java中,有三个关键常量决定了树化与退化的阈值:

/** * 1. 树化阈值:当桶中链表长度大于该值时,尝试转为红黑树 */ static final int TREEIFY_THRESHOLD = 8; /** * 2. 退化阈值:当扩容或删除节点导致树节点数小于该值时,转回链表 */ static final int UNTREEIFY_THRESHOLD = 6; /** * 3. 最小树化容量:只有当数组总容量大于该值时,才会真正进行树化 */ static final int MIN_TREEIFY_CAPACITY = 64;

二、 树化的“双重条件”深度逻辑

很多开发者只记得“链表长度 > 8”,但实际上源码中存在一个隐藏的判定逻辑

1. 触发入口:putVal方法

当我们在put一个元素时,如果发生碰撞且当前是链表结构,会进入以下逻辑:

// JDK 1.8 putVal 部分源码 for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); // 插入新节点(尾插法) if (binCount >= TREEIFY_THRESHOLD - 1) // 如果链表长度达到 8 treeifyBin(tab, hash); // 尝试树化 break; } // ... 忽略省略部分 }

2. 核心判定:treeifyBin方法

进入treeifyBin后,并不是直接转红黑树,它会先检查数组的长度:

final void treeifyBin(Node<K,V>[] tab, int hash) { int n, index; Node<K,V> e; // 【核心判定】 // 如果数组为空,或者数组长度 n < 64,则优先选择扩容而不是树化 if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) resize(); else if ((e = tab[index = (n - 1) & hash]) != null) { // 只有数组长度 ≥ 64 且链表长度 > 8,才会执行真正的树化逻辑 // ... 将 Node 转换为 TreeNode 的过程 } }

三、 深度思考:背后的数学与工程考量

1. 为什么是 8?—— 泊松分布

根据HashMap源码注释,节点在哈希桶中的频率遵循泊松分布。在负载因子为 0.75 的情况下,链表长度达到 8 的概率极低,约为 0.00000006。

设计用意:正常情况下,我们几乎不会遇到树化。红黑树是为了应对那些哈希函数设计不佳,甚至遭受恶意哈希攻击导致大量碰撞的情况。

2. 为什么退化阈值是 6 而不是 7?

这是为了留出缓冲区。如果退化阈值也是 8,那么当一个桶的节点数在 7 和 8 之间反复变动时,会引起频繁的“树化 <-> 退化”转换。这会导致大量的TreeNodeNode对象的创建与销毁,严重影响性能。

3. 节点结构的巨大变化

树化不仅仅是逻辑变了,底层存储的对象类型也发生了质变:

  • 链表节点 (Node):包含hash,key,value,next

  • 树节点 (TreeNode):继承自LinkedHashMap.Entry,除了基本属性,还增加了parent,left,right,prev,red(红黑属性)。

空间代价TreeNode占用的内存空间大约是普通Node2 倍


四、 总结:HashMap 的进化准则

  1. 链表转红黑树:当前桶链表长度且数组总容量

  2. 红黑树转链表:在扩容或删除元素时,若树中节点数

  3. 核心哲学

    • 容量小、碰撞多:通过resize扩容来平摊碰撞。

    • 容量大、碰撞多:通过treeify提升查询效率(从 O(n) 降至 O(log n))。


💡 面试贴士

在面试中,如果面试官问:“HashMap 什么时候树化?”,完整的回答应该是:

“当链表长度超过 8 时,HashMap 会调用treeifyBin方法。但该方法内部会先判断数组容量,如果容量小于 64,会优先扩容;只有容量大于等于 64 且链表长度达到 8,才会正式转换为红黑树。”

关于作者: 💡予枫,某高校在读研究生,专注于 Java 后端开发与多模态情感计算。💬欢迎点赞、收藏、评论,你的反馈是我持续输出的最大动力!

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:

https://cloud.tencent.com/developer/support-plan?invite_code=9wrxwtlju1l

当前加入还有惊喜相送!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1145690.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HCIP代码小练-2

网络架构PC1和PC2电脑配置AR1的基础配置缺省路由实现全网通AR2的基础配置匹配回包的静态路由AR3的基础配置缺省路由实现全网通PC1和PC2实现私网互联(建立GRE链接)AR1配置GREAR3配置GRE测试AR1是否可以ping通AR3检查PC1PC2的情况是否可以ping通验证通过实现PC1与PC2是否可以直接…

通信原理篇---双极性不归零码的功率谱密度

第一幕&#xff1a;回顾与对比先快速对比两种编码的“体质差异”&#xff1a;特性单极性NRZ双极性NRZ表示1V&#xff08;如1V&#xff09;V&#xff08;如1V&#xff09;表示00V-V&#xff08;如-1V&#xff09;平均电压&#xff08;等概率时&#xff09;0.5V0V核心问题有直流分…

HCIP代码小练-1

进行网段划分&#xff1a;1.区分还回网段&#xff08;环回接口&#xff1a;路由器的虚拟接口&#xff0c;一般用于模拟测试&#xff0c;不需要设备支撑&#xff09;及骨干链路的网段划分。2.将192.168.1.0 24 划分成两个子网并进行环回网段的分配。3.因为骨干链路只用两个接口&…

通信原理篇---单极性归零码与双极性归零码

第一部分&#xff1a;单极性归零码第一幕&#xff1a;老问题和新思路还记得单极性不归零码&#xff08;NRZ&#xff09;吗&#xff1f;亮1秒1&#xff0c;灭1秒0。它的最大问题是&#xff1a;长时间发1时&#xff0c;信号一直是平的&#xff0c;接收方容易丢节奏。怎么解决&…

【无人机路径规划】基于快速随机扩展树算法RRT避开长方体、圆柱体、球体三类障碍物,生成从起点到终点的无碰撞路径附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1…

【数据驱动】基于时域数据的分数混沌系统的稀疏识别附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1…

C++ IDE

一、先明确核心需求&#xff1a;不同场景选不同 IDEC IDE 的选择核心看你的使用场景 —— 是新手入门、高校学习&#xff0c;还是企业级开发、跨平台项目&#xff0c;不同场景的最优解不同&#xff0c;先帮你梳理主流选项&#xff1a;IDE 名称核心定位新手友好度适用场景收费 /…

AI原生应用开发:自然语言理解开源工具推荐

AI原生应用开发&#xff1a;自然语言理解开源工具推荐 关键词&#xff1a;AI原生应用、自然语言理解&#xff08;NLU&#xff09;、开源工具、意图分类、实体识别、对话系统、多模态交互 摘要&#xff1a;在AI原生应用&#xff08;AI Native Apps&#xff09;时代&#xff0c;让…

浩思动力混动系统赋能吉利雷达金刚PHEV高性能皮卡上市

近日,浩思动力超级电混系统正式搭载于吉利雷达金刚PHEV山地版车型。该车型为混动皮卡,以“山地高原动力之王”为定位,面向西南、西北等高原及山区复杂地形,覆盖户外运输工程作业、越野探险等应用场景,充分展现了浩思动力在高性能混合动力领域的系统化技术实力。作为新一代动力总…

虚拟机假死?SSH 能连却卡 Logo 界面

title: “虚拟机假死&#xff1f;SSH 能连却卡 Logo 界面” date: 2026-1-11 20:30 categories: [技术] tags: [技术&#xff0c;分享] 虚拟机假死&#xff1f;SSH 能连却卡 Logo 界面 作为一名后端开发&#xff0c;虚拟机常常是我们用来跑中间件&#xff08;MySQL、Redis、Roc…

《Numba AOT编译核心技术:斩断JIT启动延迟的实操手册》

Numba的JIT编译曾凭借动态代码加速能力成为很多开发者的首选,但它存在的冷启动滞涩感却在不少低延迟需求场景里成为难以突破的技术壁垒,尤其是在工业实时监测、高频数据推理这类对响应速度要求严苛的领域,这种滞涩感带来的负面影响会被无限放大。比如在某实时工业传感器数据…

图像形态学+边缘检测及CNN关联

引言&#xff1a;今天的学习围绕“图像特征提取”展开&#xff0c;从传统的图像形态学操作&#xff0c;到精准的Sobel边缘检测&#xff0c;再到深度学习中CNN的核心逻辑&#xff0c;我们一步步揭开了计算机“看懂”图像的底层原理。传统算法是深度学习的基础&#xff0c;而深度…

连锁饮品店安全用电白皮书:能源设备智能管控与预警

1.背景随着消费升级浪潮的推进&#xff0c;连锁饮品行业迎来规模化扩张高峰&#xff0c;全国门店数量已突破50万家&#xff0c;密集分布于商圈、社区、交通枢纽等人员聚集区域。然而&#xff0c;在行业高速发展的背后&#xff0c;用电安全隐患正成为制约企业稳健运营的核心痛点…

踩坑三个月,我用 Blazor 重构了一个 AI UI 协议,这些教训值得你看看

写在前面 说实话&#xff0c;接手这个项目的时候我心里是打鼓的。 你知道那种感觉吗&#xff1f;老板丢过来一个需求&#xff1a;"AI 要能动态生成 UI&#xff0c;而且要跨平台、安全、还要支持 Blazor"。我当时就在想&#xff0c;这不是要我上天吗&#xff1f; 但…

“刷房子这点事,怎么就成了动态规划经典题?”——聊透 Paint House 背后的思维方式

“刷房子这点事,怎么就成了动态规划经典题?”——聊透 Paint House 背后的思维方式 说实话,第一次看到「粉刷房子(Paint House)」这道题的时候,很多人内心是抗拒的。 “就刷个房子,还能刷出算法味儿来?” “这不就是选颜色吗?” “怎么一写就要 DP?” 但你真做过、…

Java Web的学习路径

一、前置准备阶段&#xff1a;搞定开发环境&#xff08;1-2 天&#xff09; 这一步是基础中的基础&#xff0c;先把工具配好&#xff0c;避免后续学习被环境问题卡壳。 核心任务 安装核心工具 JDK&#xff08;推荐 8/11 版本&#xff0c;企业主流&#xff09;&#xff1a;学…

【图像传输】基于MPSK算法实现图像传输系统附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1…

67、RNN的AI歌词生成案例(构建数据集)

RNN的AI歌词生成案例&#xff08;构建数据集&#xff09;一次拿五个数据提供的数据&#xff08;最多只能到倒数第二个词&#xff09;&#xff0c;若是提供的是最后一个词&#xff0c;则无法再预测了构建数据集对象&#xff0c;定义构建更简单的API

大模型Function Calling实战指南:从原理到代码,让AI更强大

本文详解大模型函数调用(Function Calling)技术&#xff0c;包括核心概念、与ReACT的区别、工具定义格式及应用场景。通过Python代码示例展示如何让大模型执行计算任务&#xff0c;获取更准确结果。Function Calling使大模型能与外部服务交互&#xff0c;适用于API调用、数据库…

基于Python的商场停车管理系统的设计与实现_szvoh5b2

前言基于Python的商场停车管理系统是一个集车位管理、车辆识别、计费收费、数据统计与用户服务于一体的智能化平台&#xff0c;通过物联网、计算机视觉与数据库技术&#xff0c;实现停车场的高效运营与用户体验优化。一、项目介绍 开发语言&#xff1a;Python python框架&#…