clear()不销毁底层数组,仅遍历table将各桶置null并重置size和modcount;数组容量、结构及内存地址均保持不变,支持高效复用,但不保证线程安全。

clear() 方法并不销毁底层数组,而是高效地将每个桶(数组元素)设为 null,同时重置计数器和状态变量。
核心操作:逐桶置空,不重建数组
HashMap 的 clear() 不会 new 新数组,也不调用 resize()。它只做两件事:
- 遍历当前
table数组,对每个非空位置执行tab[i] = null(JDK 8+ 中通过Unsafe.putObjectVolatile或 CAS 保证可见性) - 将
size、modCount等字段重置为 0
为什么能复用原数组?结构设计决定的
HashMap 底层是 Node<k>[] table</k>,数组本身只负责“引用容器”角色。清空时只需切断所有 Node 引用,数组对象及其内存空间仍保留在堆中,后续 put() 可直接复用。
- 数组长度(capacity)和负载因子(loadFactor)完全不变
- 若之前扩容到 64,
clear()后仍是容量 64 的数组,插入新数据无需立即扩容 - 这对高频复用场景(如线程局部缓存、批处理中间 Map)明显优于反复
new HashMap()
并发安全提示:非线程安全,但 clear 本身无锁
普通 HashMap 的 clear() 是线程不安全的。但它本身不加锁、不阻塞,只是批量写 null —— 这意味着:
- 若其他线程正在
put或get,可能看到部分清空、部分未清空的中间状态(不保证原子性) - 没有“锁释放”动作,因为 HashMap 本身在 JDK 8+ 不依赖显式锁保护整个表;单个 bin 的修改才可能用
synchronized锁头节点 - 如需线程安全清空,应使用
ConcurrentHashMap.clear(),它通过分段 CAS 保证各桶清空可见性
实际影响:快、省、但要注意残留引用
清空后:
- 内存占用几乎不变(数组对象还在,只是 Node 引用断开)
- 下次插入相同数量元素,大概率不触发扩容
- 但若 key 或 value 被外部强引用持有,GC 仍无法回收这些对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











