hashmap红黑树退化为链表仅发生在扩容迁移过程中,当某桶迁移后节点数≤6时调用untreeify()转链表;删除、插入、clear等操作均不触发退化,设计上为避免频繁结构切换带来的性能开销。

HashMap 的红黑树退化为链表,**只发生在扩容(resize)过程中**,没有其他触发场景。
退化仅在扩容迁移时发生
红黑树不会因为删除元素、插入新元素、调用 clear() 或手动干预而退化。只有当 resize 执行到某个树桶的迁移阶段(split 方法),且迁移后该桶中剩余的红黑树节点数 ≤ 6,才会调用 untreeify() 转为链表。
- 日常 remove() 操作:哪怕删到只剩 1 个节点,树结构仍保留
- put() 或 replace():不检查节点数,也不触发退化
- clear():清空所有桶,但不是“退化”,而是直接置 null 或重置引用
- 没有 public API 可强制退化,阈值 6 是硬编码,不可配置
为什么不能在非扩容时退化
设计上刻意避免运行时结构震荡:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 频繁增删会导致节点数在 7、8 附近波动,若每次删除都检查,可能刚删一个就退化、再 put 一个又树化,开销巨大
- 红黑树的旋转、着色、节点转换本身有成本,非必要不启动
- 扩容是天然的“批量重组织”时机,此时统一判断更高效、更可控
ConcurrentHashMap 的行为更严格
它同样只在 transfer(并发扩容)中退化,且要求当前树桶已加锁、迁移完成、节点数 ≤ 6。由于多线程竞争和 TreeBin 锁机制,它比 HashMap 更难触发退化,实际中很多树桶会长期保持红黑树形态。
不复杂但容易忽略:退化不是响应式操作,而是扩容附带的一次性整理动作。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










