WeakHashMap 适合做内存敏感缓存,核心在于其 key 是弱引用——当 key 无强引用时 GC 可回收并自动移除条目;value 为强引用,若反向引用 key 会导致内存泄漏;不支持 TTL/LRU,仅响应 GC,适用于键生命周期由外部控制的场景。

WeakHashMap 适合做内存敏感的缓存,核心在于它的键(key)是弱引用的——当 key 没有其他强引用指向它时,GC 可以回收该 key 对应的整个映射条目。这避免了传统 HashMap 导致的内存泄漏,特别适用于“以对象为键、生命周期不确定”的缓存场景。
为什么 WeakHashMap 能自动清理缓存项
WeakHashMap 内部使用的是 WeakReference 包装 key,value 仍是强引用。这意味着:
- 只要外部不再持有该 key 的强引用,下次 GC 时 key 就可能被回收
- 一旦 key 被回收,WeakHashMap 在后续的
get、put、size等操作中会主动扫描并清除对应 Entry(通过 ReferenceQueue 实现) - value 不会自动变弱——如果 value 又反过来强引用了 key(比如内部类、闭包),就会阻止 key 回收,形成循环引用,导致缓存项无法释放
典型用法:缓存基于对象身份的计算结果
例如缓存某个复杂对象的哈希码、校验和或格式化字符串,且只希望在该对象还被业务代码使用时保留结果:
private final Map<MyData, String> cache = new WeakHashMap<>();
public String getFormatted(MyData data) {
return cache.computeIfAbsent(data, d -> d.formatExpensively());
}
注意:MyData 必须正确重写 equals 和 hashCode,否则 WeakHashMap 的查找逻辑会失效(它依赖哈希桶定位,但不保证 equals 语义——因为 key 可能已被回收,Entry 已不存在)。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
关键注意事项与避坑点
WeakHashMap 不是“万能自动缓存”,实际使用中需警惕:
- 不要用 String、Integer 等常量池对象作 key:它们被 JVM 强引用,永远不会被 GC,缓存项永远不释放
- value 避免反向持有 key:比如 value 是一个匿名内部类实例,捕获了 key 的引用,会导致 key 无法回收
-
不适用于需要稳定存活时间的缓存:GC 时间不可控,缓存可能随时消失;如需 TTL 或 LRU,应选
LinkedHashMap+ 定时清理,或用 Caffeine/Ehcache - size() 返回的是当前可达 key 的数量,不是精确实时值:因清理发生在访问时,调用 size 前可能已有 key 被回收但尚未清理 Entry
替代方案对比:什么情况下不该用 WeakHashMap
如果你需要:
- 按访问频次淘汰(LFU)、最近使用淘汰(LRU)→ 用
LinkedHashMap重写removeEldestEntry - 设置过期时间(TTL/TTI)→ 用
Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) - 支持并发且高性能 → WeakHashMap 本身非线程安全,要加锁;Caffeine 默认线程安全
- value 也要弱引用 → WeakHashMap 不支持,可考虑
Map<K, WeakReference<V>>手动管理,但需自行处理 null value 和清理逻辑
WeakHashMap 解决的是“键生命周期由外部控制”的特定问题,不是通用缓存容器。用对场景,它轻量又可靠;用错场景,反而引入不确定性。

















