weakhashmap 的自动清除依赖 jvm 垃圾回收、弱引用机制和操作触发协同完成,每次调用 get/put/size 等方法前会清理已回收键的条目,属懒执行且不额外开销。

WeakHashMap 的自动清除不是靠定时扫描或后台线程,而是依赖 JVM 垃圾回收 + 弱引用机制 + 操作触发三者协同完成。
它在对象被 GC 回收后,并不会“立刻”从 Map 中删除对应条目,而是等你下一次调用 get、put、size、keySet、entrySet 等方法时,才顺手清理掉那些已被 GC 回收的键。
具体流程如下:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
键被包装成 WeakReference
每个键在插入时会被封装为WeakReference<k></k>,并关联到 WeakHashMap 内部私有的ReferenceQueue。GC 发现键不可达,将其入队
当外部不再持有该键的强引用,JVM 在某次 GC 过程中判断其仅剩弱引用,就会回收该键对象,并把对应的WeakReference实例加入内部引用队列。-
下次操作前主动清理
所有公开 API(如get()、put())内部都会先调用私有方法expungeStaleEntries():- 遍历引用队列,取出已入队的失效
WeakReference - 根据
referent == null判断键是否已被回收 - 定位哈希表中对应槽位,移除整个
Entry(包括 value)
- 遍历引用队列,取出已入队的失效
这意味着:
- 不调用任何方法,就不会清理,哪怕键早已被 GC
- 清理是“懒执行”的,但每次访问都帮你扫一遍,不额外开销
-
size()返回的是当前存活的 Entry 数,可能比插入数小很多
关键提醒:
- value 仍是强引用,若 value 反向持有 key(如内部类、Lambda 捕获),会导致 key 无法被 GC,整个 Entry 卡住不释放
- String 字面量、Integer 小值(-128~127)等常量池对象有强引用驻留,不适合作为 WeakHashMap 的键
- 遍历时建议用
entrySet().iterator(),并在调用next()后检查entry.getKey() != null,避免 NPE
本质上,WeakHashMap 把“何时清理”的决策权交给了 GC,自己只负责在被使用时及时同步状态。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










