HashMap链表转红黑树需同时满足:桶内链表节点数≥8且底层数组长度≥64;否则优先扩容;红黑树节点≤6时退化为链表。

Java 的 HashMap 在链表过长时,不是放任它继续变长,而是主动触发结构升级——当条件满足,就把链表转成红黑树。
链表转红黑树的两个硬性条件
这个转换不是只看链表长度,而是必须同时满足:
- 当前桶(bucket)里的链表节点数 ≥ 8
- 整个 HashMap 的底层数组长度 ≥ 64
如果数组还不够大(比如刚初始化或扩容次数少),即使链表长度到了 8,HashMap 也会优先选择扩容(数组长度翻倍),而不是树化——因为扩容后哈希分布更散,冲突自然减少,性价比更高。
红黑树带来的性能提升
链表查找是逐个遍历,最坏时间复杂度 O(n);而红黑树是自平衡二叉搜索树,查找、插入、删除都稳定在 O(log n)。例如,一个含 1024 个冲突元素的桶,链表平均要查 500+ 次,红黑树最多查 10 次左右。
立即学习“Java免费学习笔记(深入)”;
注意:树化后,所有操作(get/put/remove)都走红黑树逻辑,但 key 的比较仍依赖 equals() 和 hashCode(),不是单纯比大小。
红黑树也会退化回链表
这不是单向升级,而是动态适应:
- 当某个桶中的红黑树节点数 ≤ 6 时,会自动退化为链表
- 退化发生在 resize 或 remove 过程中,由
untreeify()方法执行
这样设计是为了避免小规模数据下红黑树的额外开销(节点结构更复杂、旋转维护成本高),保持轻量和高效。
其他辅助机制也在降低链表变长的概率
除了树化,HashMap 还从源头减少冲突发生:
-
扰动函数:对原始 hashCode 做
h ^ (h >>> 16)异或,让高位参与索引计算,分散低位重复导致的聚集 - 负载因子控制:默认 0.75,当元素数量达到容量 × 0.75 就触发扩容,预留足够空间缓冲冲突
-
2 的幂次容量:配合
(n - 1) & hash位运算快速取模,也使哈希分布更均匀


















