江西住房和城乡建设厅网站该网站尚未备案 腾讯云
2026/4/22 15:21:53 网站建设 项目流程
江西住房和城乡建设厅网站,该网站尚未备案 腾讯云,承包企业管理系统,互联网营销推广#x1f342; 枫言枫语#xff1a;我是予枫#xff0c;一名行走在 Java 后端与多模态 AI 交叉路口的研二学生。 “予一人以深耕#xff0c;观万木之成枫。” 在这里#xff0c;我记录从底层源码到算法前沿的每一次思考。希望能与你一起#xff0c;在逻辑的丛林中寻找技术…枫言枫语我是予枫一名行走在 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(NodeK,V[] tab, int hash) { int n, index; NodeK,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 之间反复变动时会引起频繁的“树化 - 退化”转换。这会导致大量的TreeNode与Node对象的创建与销毁严重影响性能。3. 节点结构的巨大变化树化不仅仅是逻辑变了底层存储的对象类型也发生了质变链表节点 (Node)包含hash,key,value,next。树节点 (TreeNode)继承自LinkedHashMap.Entry除了基本属性还增加了parent,left,right,prev,red红黑属性。空间代价TreeNode占用的内存空间大约是普通Node的2 倍。四、 总结HashMap 的进化准则链表转红黑树当前桶链表长度且数组总容量。红黑树转链表在扩容或删除元素时若树中节点数。核心哲学容量小、碰撞多通过resize扩容来平摊碰撞。容量大、碰撞多通过treeify提升查询效率从 O(n) 降至 O(log n)。 面试贴士在面试中如果面试官问“HashMap 什么时候树化”完整的回答应该是“当链表长度超过 8 时HashMap 会调用treeifyBin方法。但该方法内部会先判断数组容量如果容量小于 64会优先扩容只有容量大于等于 64 且链表长度达到 8才会正式转换为红黑树。”关于作者 予枫某高校在读研究生专注于 Java 后端开发与多模态情感计算。欢迎点赞、收藏、评论你的反馈是我持续输出的最大动力我的博客即将同步至腾讯云开发者社区邀请大家一同入驻https://cloud.tencent.com/developer/support-plan?invite_code9wrxwtlju1l当前加入还有惊喜相送

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询