hashmap在jdk 8中引入红黑树是为了避免链表过长导致查找退化为o(n),当桶中链表长度≥8且数组长度≥64时转为红黑树,节点数≤6时退化回链表;treenode继承node并扩展树结构字段,支持可逆转换。

HashMap 在 JDK 8 中引入红黑树,不是为了“替代”链表,而是为了解决**链表过长导致查找性能退化**的问题。当同一个桶(bucket)中链表节点数达到阈值(默认 8),且当前数组长度 ≥ 64 时,该链表会转为红黑树;反之,若树中节点数 ≤ 6,则退化回链表。
为什么链表长了会影响性能?
哈希冲突发生时,HashMap 用链表串联同桶中的元素。链表查找是 O(n) 时间复杂度——如果大量键哈希值落在同一桶,比如因哈希函数不均或恶意构造数据,链表可能很长,get/put 操作就会变慢。极端情况下,退化成类似线性查找,失去哈希表 O(1) 的优势。
红黑树如何改善查找效率?
红黑树是一种自平衡二叉搜索树,查找、插入、删除的时间复杂度稳定在 O(log n)。当链表长度 ≥ 8,O(n) 已明显劣于 O(log n)(例如 n=8 时,log₂8=3;n=1000 时,log₂1000≈10,而线性是1000)。转为红黑树后,相同桶内元素的查找不再逐个遍历,而是按 key 的 自然顺序或比较器顺序 进行二分式导航。
注意:树化前提是 key 必须实现 Comparable 接口(如 String、Integer),或构造 HashMap 时传入 Comparator,否则无法比较大小,树化会失败,仍维持链表。
树化与退化的触发条件
不是一有冲突就树化,JDK 8 设计了两个硬性条件,兼顾性能与空间开销:
- 链表长度 ≥ 8:这是树化的下限阈值,防止小规模数据频繁树化带来额外开销
- table 数组长度 ≥ 64:说明哈希表已足够大,大概率不是因为初始容量太小导致哈希分布密集,而是真实发生了较严重的哈希碰撞
满足两者才树化;反向地,当树中节点数 ≤ 6 时,会自动转回链表——因为少量节点下,链表的内存更紧凑、遍历开销更低,红黑树的平衡维护反而得不偿失。
红黑树节点与链表节点共用 Node 类?
不是。JDK 8 新增了 TreeNode 类,继承自 Node,额外包含 parent、left、right、prev 和 red 等字段,支持树结构操作。但 TreeNode 仍保留 hash、key、value、next 字段,兼容原有 Node 行为。扩容时,TreeNode 可以拆分为两棵子树,也能还原为链表节点,保证结构可逆。










