1. WeakHashMap也是Map中的一种,它的特殊之处在于它其中的对象,可能会被GC自动回收,也就是数据会凭空消失,即使程序员没有调用remove()或者clean()方法,那么你就会有疑问了,**这种数据会凭空消失**,那为什么还要设计这种类?其实答案是WeakHashMap主要用于缓存的情况,缓存一般用于内存不够的情况下,设置缓存可以大大提高系统的效率,缓存的空间也是有限的所以说, <br /> WeakHashMap用来存储需要缓存的对象,如果命中了当然是很好的,如果没命中也无关紧要,而且正是这种自动回收不需要(GC认为不需要)的数据,反而能帮我们管理缓存的空间,WeakHashMap的特性和HashMap的特性还是很相似的\

一、WeakHashMap的三种引用(强引用,软引用,弱引用)

  • 强引用,声明出来决对不会被GC回收
  1. Integer i = 1;
  • 软引用,只有当JVM内存不够时,才会被回收
  1. Integer prime = 1;
  2. SoftReference<Integer> soft = new SoftReference<Integer>(prime);
  3. prime = null;
  • 弱引用,下个垃圾回收周期时该对象就会被回收
    1. Integer prime = 1;
    2. WeakReference<Integer> soft = new WeakReference<Integer>(prime);
    3. prime = null;

二、WeakHashMap的构造函数

和所有的Map实现类的构造函数相同,都为4个,在此就不过多介绍了

①指定初始化容量(必须为2的次幂)和负载因子

②指定初始化容量(必须为2的次幂)使用默认负载因子0.75

③空构造函数,使用默认容量16,和默认负载因子0.75

④创造一个包含子Map的WeakHashMap

三、WeakHashMap的变量声明

首先,Map结构都会存在的几个声明

table, size, threshold, loadFactor, modCount。
①table是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的”key-value键值对”都是存储在Entry数组中的。
②size是WeakHashMap的大小,它是WeakHashMap保存的键值对的数量。
③threshold是WeakHashMap的阈值,用于判断是否需要调整WeakHashMap的容量。threshold的值=”容量*负载因子”,当WeakHashMap中存储数据的数量达到threshold时,就需要将WeakHashMap的容量加倍。
④loadFactor就是负载因子。
⑤modCount是用来实现fail-fast机制的。

但是,需要注意的是在WeakHashMap中出现了一个新的变量声明

  1. private final ReferenceQueue<Object> queue = new ReferenceQueue<>();

这里出现了一个ReferenceQueue队列,这个队列是干嘛的呢?

下面是我在带你读懂 Reference 和 ReferenceQueue中查询到的

Reference
主要是负责内存的一个状态,当然它还和java虚拟机,垃圾回收器打交道。Reference类首先把内存分为4种状态Active,Pending,Enqueued,Inactive。

  • Active,一般来说内存一开始被分配的状态都是 Active,
  • Pending 大概是指快要被放进队列的对象,也就是马上要回收的对象,
  • Enqueued 就是对象的内存已经被回收了,我们已经把这个对象放入到一个队列中,方便以后我们查询某个对象是否被回收,
  • Inactive就是最终的状态,不能再变为其它状态。

ReferenceQueue 引用队列,在检测到适当的可到达性更改后,垃圾回收器将已注册的引用对象添加到队列中,ReferenceQueue实现了入队(enqueue)和出队(poll),还有remove操作,内部元素head就是泛型的Reference。

也就是说,其实WeakHashMap的随机回收实现是通过这个ReferenceQueue来实现的

换句话说,WeakHashMap中的数据是放置到它里面后,才实现回收的

WeakHashMap和HashMap都是通过”拉链法”实现的散列表。它们的源码绝大部分内容都一样,这里可以看前面关于HashMap的解释