WeakHashMap

在继承AbstractMap中的子类中除了Hashmap外还有WeakHashmap。

public class WeakHashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V> 

在这里我们可以看到 WeakHashmap和Hashmap一样都是继承AbstractMap类 的,实现的接口也是Map接口。

接下来我们看一下他的一些常量。

private static final int DEFAULT_INITIAL_CAPACITY = 16;  //默认大小
private static final int MAXIMUM_CAPACITY = 1 << 30;  //最大容量
private static final float DEFAULT_LOAD_FACTOR = 0.75f;  //默认的填充因子

在这里我们可以看到 是基于Entry(存储键值对)数组实现的。

Entry<K,V>[] table;

这里还有一个队列,在后面我们会说他的作用。

private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
public WeakHashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Initial Capacity: "+
                                           initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;

    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal Load factor: "+
                                           loadFactor);
    int capacity = 1;
    while (capacity < initialCapacity)
        capacity <<= 1;
    table = newTable(capacity);
    this.loadFactor = loadFactor;
    threshold = (int)(capacity * loadFactor);
}

这里是WeakHashmap 的构造方法,需要传入两个数据,默认大小和填充因子。然后多Capacity做合法性判断和限制,然后是填充因子的判断。最后会new一个table。

private Entry<K,V>[] newTable(int n) {
    return (Entry<K,V>[]) new Entry<?,?>[n];
}

这是new出来的table,就是一个Entry类型的数组。
重点来了

private void expungeStaleEntries() {
    for (Object x; (x = queue.poll()) != null; ) {
        synchronized (queue) {
            @SuppressWarnings("unchecked")
                Entry<K,V> e = (Entry<K,V>) x;
            int i = indexFor(e.hash, table.length);

            Entry<K,V> prev = table[i];
            Entry<K,V> p = prev;
            while (p != null) {
                Entry<K,V> next = p.next;
                if (p == e) {
                    if (prev == e)
                        table[i] = next;
                    else
                        prev.next = next;
                    // Must not null out e.next;
                    // stale entries may be in use by a HashIterator
                    e.value = null; // Help GC
                    size--;
                    break;
                }
                prev = p;
                p = next;
            }
        }
    }
}

这段很长的代码,里边出现了前面的queue 。这里的x是从queue中出来的,前提能实现queue.poll()方法。然后,这是加了一个锁吗?再然后,是吧x给Entry节点。再调用indexFor()方法。

private static int indexFor(int h, int length) {
    return h & (length-1);
}

在算哈希值。这个方法。然后就是对散列表的操作。注意有一句e.value = null; // Help GC 这里有用到GC回收。这是和Hashmap不同的。这里的queue是ReferenceQueue类型的。我们来说一下ReferenceQueue。

Reference
Reference主要负责内存中的一个状态。他和Java的虚拟机,垃圾回收器有关。Referenc类将内存分为四个状态,
Activite,>一般来说,内存一开始被分配的都是Activie
Pending,
>快要放入队列中的对象
Enqueued,——》已经被内存回收的对象,并把它放入队列中,方便查看某个对象是否被回收。
inacvite.——》最终状态。
ReferenceQueue
垃圾回收器将已注册的引用对象添加到队列中。

总的来说,WeakHashmap 存储的是弱键。是当没有节点(数据)失去引用后,会被GC回收。这是自动的。原因就是使用的queue出数据,而queue是一个ReferenceQueue类型的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值