导读摘要:
WeakHashMap 是一种可以提供自我清理行为的哈希表,与 HashMap 不同的是,它的键是通过“弱引用”来保存的,这意味着在键不再被外部引用时,它将被自动从 WeakHashMap 中删除

摘要:

WeakHashMap 是一种可以提供自我清理行为的哈希表,与 HashMap 不同的是,它的键是通过“弱引用”来保存的,这意味着在键不再被外部引用时,它将被自动从 WeakHashMap 中删除。WeakHashMap 最常用于缓存昂贵但随时可用的对象,从而防止内存泄漏和过度缓存。

1. WeakHashMap 和 HashMap 的区别

weakhashmap(weakhashmap和hashmap的区别)

WeakHashMap 与 HashMap 有以下区别:

  • WeakHashMap 的键是通过“弱引用”来保存的,HashMap 的键则是通过普通引用来保存的。
  • WeakHashMap 允许键值为 null,而 HashMap 不允许。
  • WeakHashMap 不保证映射关系的顺序,而 HashMap 可以通过 LinkedHashMap 来保证插入顺序或访问顺序。
  • 由于 WeakHashMap 的键是弱引用,因此它的某些方法和操作演变成了类似于写保护存储器的行为。

2. WeakHashMap 的内部实现

weakhashmap(weakhashmap和hashmap的区别)

WeakHashMap 的内部结构,与 HashMap 非常相似,都是由“桶”(Bucket)数组和“链表”(链地址法)组成,因此它们的查询、插入和删除操作的时间复杂度都是 O(1)。但WeakHashMap 中的键值对是通过“弱引用”保存的,其内存管理与垃圾回收机制有着显著的差别。

  • 弱引用是指一种不会抵御垃圾回收的对象引用,如果一个对象的弱引用数量为 0,那么这个对象就可以被回收了。
  • WeakHashMap 通过 WeakReference 类保存键,因此当键不再被外部引用时,所关联的键值对会被自动从 WeakHashMap 中删除。
  • 在调用 WeakHashMap 的 put()、remove() 或 size() 等方法时,会先调用弱引用队列的 poll() 方法,查看是否有键已经被回收,如果有,则将此键从 WeakHashMap 中删除。

3. WeakHashMap 的使用场景

weakhashmap(weakhashmap和hashmap的区别)

WeakHashMap 最常用于缓存昂贵但随时可用的对象。例如,使用 WeakHashMap 缓存 Bitmap 图像资源,可以确保当内存不足时,不会因为 Bitmap 图像资源占用太多内存而导致崩溃。在以下情形中,可使用 WeakHashMap:

  • 缓存高质量对象(如图片、音频等)时,可以避免内存泄漏。
  • 当需要保存键或值为 null 的映射关系时,可以使用 WeakHashMap 代替 HashMap。
  • 当需要在多线程中使用映射表时,可以使用 ConcurrentHashMap 代替 WeakHashMap。

4. WeakHashMap 的局限性

weakhashmap(weakhashmap和hashmap的区别)

虽然 WeakHashMap 具有许多有用的特性,但也有一些局限性:

  • 键值对的自动删除仅适用于键,而值不受控制。
  • WeakHashMap 的性能与 HashMap 相比存在微小的损失,因为它需要维护弱引用队列的一些开销。
  • WeakHashMap 的弱引用机制只适用于对象的生命期。如果对象没有被持续引用,它的生命期就结束了。但如果准备把对象从 WeakHashMap 中移除,对象可能仍在进程中其他地方被使用,这可能导致问题。

总之,WeakHashMap 是一个用于处理昂贵但随时可用的对象缓存的有用工具,它会自动清除不再被引用的键值对,从而避免了内存泄漏和过度缓存。但需要注意它的一些限制,例如值不受控制、弱引用机制只适用于对象的生命期等。