红黑树退化为链表仅发生在resize迁移阶段且节点数≤6;日常put/remove不触发,避免频繁切换抖动,6与8构成缓冲区间以降低开销。

红黑树节点退化为链表,只发生在扩容迁移过程中,且必须满足节点数 ≤ 6。
退化的唯一时机:resize 时的迁移阶段
日常的 put、remove 操作不会触发退化。只有在 HashMap 执行 resize(扩容或缩容)时,调用 transfer 方法对桶中红黑树进行拆分迁移,才会检查节点数量:
- 迁移后,若该树在新数组中对应桶里的节点数 ≤ 6,就调用 untreeify() 转为普通链表
- 如果迁移后只剩 1 个或 0 个节点,分别变成单节点链表或 null
- 即使连续 remove 导致树中只剩 5 个节点,也不会立刻退化——必须等到下一次 resize
为什么是阈值 6,不是 8 或其他数
6 和树化阈值 8 构成缓冲区间,避免结构频繁切换:
- 若树化和退化都用 8,链表长度在 7→8→7 之间波动,就会反复树化又退化
- 这种震荡会带来巨大开销:构造/销毁树节点、重新平衡、内存分配等
- 留出 2 的差值(8→6),相当于给哈希分布波动留出安全余量
退化不依赖当前容量大小
和树化不同,退化没有数组容量门槛:
- 无论 table.length 是 64、128 还是 1024,只要迁移后节点数 ≤ 6,就退化
- 这个逻辑写死在 TreeNode.split() 方法里,不可配置
- 退化后,该桶后续插入走链表流程,直到再次满足树化条件
ConcurrentHashMap 的退化更谨慎
在并发场景下,退化行为进一步受限:
- 同样要求迁移后节点数 ≤ 6
- 但必须在成功获取 bin 锁的前提下完成迁移和判断
- 高并发下多个线程协作迁移,实际退化频率比 HashMap 更低
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











