前言
WeakHashMap
类似HashMap
是一个基于哈希实现的无序散列表,存储内容是键值对(key-value
),是非线程安全的,但是WeakHashMap
的键是弱键。
在WeakHashMap
中,当某个键不再正常使用时,将会被自动移除。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的回收,这就使该键成为可终止的,然后被回收。回收某个键时,对应的键值对会从映射中有效地移除。因此,该类的行为与其他的 Map 实现有所不同。其定义如下:
可以看到HashMap
继承AbstractMap
,实现了Map接口。
那么WeakHashMap
是怎么实现这个弱键的呢?WeakHashMap
是通过WeakReference
和ReferenceQueue
实现的,WeakHashMap
的key
是WeakReference
类型的,将WeakReference
和ReferenceQueue
关联,ReferenceQueue
便会保存被GC
回收的“弱键”,如下(具体关于Java的四种引用类型见前文Java数据类型):
- 与
HashMap
类似,WeakHashMap
是通过数组table
保存Entry
(键值对),而每一个Entry
是单向链表,Entry
类继承WeakReference
,新建Entry
时,便会把Entry
的key
和ReferceQueue
关联 当“弱键”不再被其它对象引用,便会被GC回收时。GC回收该“弱键”时,这个“弱键”也同时会被添加到
ReferenceQueue(queue)
队列中当再次操作
WeakHashMap
时,如获取size
大小,扩容等,会先同步table和queue
,table
中保存了全部的键值对,而queue
中保存被GC回收的键值对,删除table
中被GC回收的键值对。
和HashMap
一样,WeakHashMap
是不同步的。可以使用 Collections.synchronizedMap
方法来构造同步的 WeakHashMap
。
本文源码分析基于jdk 1.8.0_121
继承关系
WeakHashMap继承关系
|
|
关系图
table
是Entry[]
型的数组,而Entry
其实是个单向链表,所以WeakHashMap
的底层实现是由数组和链表实现的,此处的Entry
和HashMap
中的Node
类似,但是Entry
继承自WeakReference<Object>
size
是WeakHashMap
的实际大小threshold
为是否需要调整WeakHashMap
的容量的阈值,等于加载因子乘以容量,当size
达到threshold
时,便对WeakHashMap
扩容loadFactor
是加载因子modCount
是修改WeakHashMap
结构的计数值,用来实现fail-fast
机制queue
用来保存被GC清除的弱引用的键
构造函数
|
|
API
|
|
源码分析
成员变量
|
|
构造函数
|
|
定位桶位置
|
|
增加元素
|
|
获取元素
|
|
删除元素
|
|
resize
|
|
清空无用键值对
|
|
Entry数据结构
|
|
遍历
假设key和value
都是String
型
- 根据
entrySet()
通过Iterator
遍历
|
|
根据
keySet()
通过Iterator
遍历12345Iterator iter = map.keySet().iterator();while(iter.hasNext()){key = (String)iter.next();value = (String)map.get(key);}根据
value()
通过Iterator
遍历1234Iterator iter = map.values().iterator();while(iter.hasNext()){value = (String)iter.next;}
可以发现,遍历WeakHashMap
的方法和遍历HashMap
的方法完全一致。