WeakHashMap和HashMap一样,是一个散列表,存储的内容也是键值对(key-value)映射,键和值都可以为null。区别是WeakHashMap的键是“弱键”(当WeakHashMap某个键不再正常使用时,会被从WeakHashMap自动删除)
WeakHashMap的继承关系
public class WeakHashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>
向WeakHashMap中添加键值对
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
V value;
final int hash;
Entry<K, V> next;
/**
* 创建新的entry.
*/
Entry(Object key, V value, ReferenceQueue<Object> queue, int hash, Entry<K, V> next) {
super(key, queue);
this.value = value;
this.hash = hash;
this.next = next;
}
//
}
WeakHashMap是通过数组table保存Entry(键值对);每个Entry实际上就是一个链表来实现的,即就是 Entry是一个键值对链表。
回收key
private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
某“弱键”不再被其它对象引用,就会被GC回收,“弱键”也同时被添加到ReferenceQueue队列中
当需要再操作WeakHashMap时,先同步table、queue,因table中保存了全部的键值对,而queue中保存的是GC回收的键值对,同步就会删除被GC回收的键值对。
put方法
private static Object maskNull(Object key) {
return (key == null) ? NULL : key;
}
public V put(K key, V value) {
Object k = maskNull(key);
int h = hash(k);
Entry<K,V>[] tab = getTable();
int i = indexFor(h, tab.length);
for (Entry<K,V> e = tab[i]; e != null; e = e.next) {
if (h == e.hash && eq(k, e.get())) {
V oldValue = e.value;
if (value != oldValue)e.value = value;
return oldValue;
}
}
modCount++;
Entry<K,V> e = tab[i];
tab[i] = new Entry<>(k, value, queue, h, e);
if (++size >= threshold)
resize(tab.length * 2);
return null;
}
插入方法:判断key是否为空,若为空则key为NULL,再计算hash值,遍历数组,通过hash查找插入位置,若存在相应hash,覆盖旧值,若不存在,构建Entry对象,再存入数组
get方法:
private static Object maskNull(Object key) {
return (key == null) ? NULL : key;
}
public V get(Object key) {
Object k = maskNull(key);
int h = hash(k);
Entry<K,V>[] tab = getTable();
int index = indexFor(h, tab.length);
Entry<K,V> e = tab[index];
while (e != null) {
if (e.hash == h && eq(k, e.get())) return e.value;
e = e.next;
}
return null;
}
查找方法:判断key是否为空,若为空则key为NULL,再计算hash值,遍历数组是否存在相同的hash,是则返回value。