WeakHashMap分析

  上一篇讲了有关WeakReference来方便的管理内存,这里来具体分析WeakHashMap。WeakHashMap是一种map,但是在实现的时候,但是这个map中entry会变少。WeakHashMap的设计思路是这样子的,当我们使用WeakHashMap来当做缓存的时候,某些记录可能会在适当的时候会被删除,这样能减少缓存所占用的空间(使用缓存的话,其实softreference更加的妥当,下篇文档讲对softreference进行解释)。

  下面看WeakHashMap的代码片段

   

public V put(K key, V value) {
        K k = (K) maskNull(key);
        int h = HashMap.hash(k.hashCode());
        Entry[] 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,V>(k, value, queue, h, e);   // 1
        if (++size >= threshold)
            resize(tab.length * 2);
        return null;
    }
上面这段代码是WeakHashMap存放记录时候的一个方法,其实方法中没有特别的地方,除了1所标记的,这里的Entry是WeakHashMap自己实现的,下面我看看Entry是怎么实现的。

private static class Entry<K,V> extends WeakReference<K> implements Map.Entry<K,V> { //2
        private V value;
        private final int hash;
        private Entry<K,V> next;


        /**
         * Creates new entry.
         */
        Entry(K key, V value,
	      ReferenceQueue<K> queue,
              int hash, Entry<K,V> next) {
            super(key, queue);   //3
            this.value = value;
            this.hash  = hash;
            this.next  = next;
        }


        public K getKey() {
            return WeakHashMap.<K>unmaskNull(get());
        }

上面的代码不是Entry的整个,只是Entry的Field部分、一个构造函数和get方法。在2这个地方,我们可以看到Entry是继承了WeakReference,在3中,我们看到了,这里我们把key进行了WeakReference,所以放我们需要这个key的时候,就可以使用上面代码中的get方法。这样,当除了map外没有其他引用指向这个key的时候,这个key就会在gc启动的时候可能被gc掉,然后gc后,指向它的reference就会被放入到queue(这功能是weakreference提供的)。当我们需要使用这个map的时候,就有可能清除掉这个map中不指向key的,也就是被gc掉的reference。如下面代码

private void expungeStaleEntries() {
	Entry<K,V> e;
        while ( (e = (Entry<K,V>) queue.poll()) != null) {
            int h = e.hash;
            int i = indexFor(h, 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;
                    e.next = null;  // Help GC
                    e.value = null; //  "   "
                    size--;
                    break;
                }
                prev = p;
                p = next;
            }
        }
    }

上面代码根据queue中的reference,删除掉map中对应reference的entry。上面的代码在我们对weakHaskMap进行读操作的时候都会执行一遍,如读取WeakHashMap的size

public int size() {
        if (size == 0)
            return 0;
        expungeStaleEntries();
        return size;
    }


下篇文章主要介绍concurrentHashMap,softreference。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值