weakhashmap通过弱引用键实现自动缓存清理,当键仅被其引用时gc可回收,随后在get/put/size等操作时惰性移除对应条目;值为强引用,需防内存泄漏;适用于对象生命周期依赖的临时元数据缓存。

WeakHashMap 通过弱引用键实现自动缓存清理,核心在于:当键对象仅被 WeakHashMap 引用时,GC 可回收该键,随后对应条目在下一次访问(如 get、put 或 size)时被自动移除。
WeakHashMap 的工作原理
WeakHashMap 内部使用弱引用(WeakReference)包装键对象,值对象仍为强引用。这意味着:
- 键对象的生命周期不受 WeakHashMap 影响——只要没有其他强引用指向它,GC 就可能回收该键
- 键被 GC 回收后,对应 Entry 并不会立即从表中删除,而是在后续哈希操作(如扩容、遍历或调用
size())时惰性清理 - 值对象不会因此自动释放,若值本身又持有对键的强引用(如闭包、内部类),会导致键无法被回收,引发内存泄漏
典型使用场景与示例
适合缓存“依赖于对象生命周期”的数据,例如:
- 为某个对象实例附加临时元数据(如调试信息、序列化上下文)
- 避免因缓存导致对象无法被回收(如监听器、GUI 组件关联配置)
- 替代手动维护
Map<object v></object>+ 显式清理逻辑
简单示例:
WeakHashMap<string integer> cache = new WeakHashMap();
String key = new String("temp"); // 非 intern 字符串,便于演示回收
cache.put(key, 42);
System.out.println(cache.get(key)); // 输出 42
key = null; // 移除唯一强引用
System.gc(); // 建议 GC(仅提示,不保证立即执行)
// 此时 key 已不可达,但 Entry 不一定立刻消失
// 下次调用 get(null) 或 size() 等操作会触发清理
System.out.println(cache.size()); // 可能为 0(取决于是否已清理)</string>
使用注意事项
WeakHashMap 不是“万能缓存”,需警惕以下陷阱:
-
键必须是可变对象的弱引用安全目标:若用字符串字面量(如
"abc")作键,因字符串常量池持有强引用,永远不会被回收 - 不能用于需要稳定存在时间的缓存:清理时机由 GC 决定,不可控;不适合做 LRU 或 TTL 缓存
-
并发不安全:和 HashMap 一样,非线程安全;多线程环境下需额外同步或改用
ConcurrentHashMap+ 手动弱引用管理 -
不要在键对象中重写
equals/hashCode依赖外部状态:一旦键被回收,Entry 清理依赖其原始 hash,若 hash 计算不稳定,可能导致残留条目
替代方案参考
若需更可控的弱/软引用缓存,可考虑:
-
java.lang.ref.ReferenceQueue+ 自定义 Map:精细控制引用入队与清理时机 -
SoftReference用于“内存敏感型缓存”(如图片缓存),比弱引用保留更久 - 第三方库如 Guava 的
CacheBuilder.weakKeys()或 Caffeine,提供组合策略(弱键 + 软值 + 过期 + 并发)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











