AI工具人
提示词工程师

Java WeakHashMap

  作为一个java开发者肯定都知道且使用HashMap,但估计大部分人都不太知道WeakHashMap。从类定义上来看,它和普通的HashMap一样,继承了AbstractMap类和实现了Map接口,也就是说它有着与HashMap差不多的功能。那么既然jdk已经提供了HashMap,为什么还要再提供一个WeakHashMap呢? 黑格尔曾经说过,存在必合理,接下来我们来看下为什么有WeakHashMap。

  先来想象一下你因为某种需求需要一个Cache,你肯定会面临一个问题,就是所有数据不可能都放到Cache里,或者放到Cache里性价比太低了。这个时候你可能很快就想到了各种Cache数据过期策略,目前也有一些优秀的包提供了功能丰富的Cache,比如Google的Guava Cache,它支持数据定期过期、LRU、LFU等策略,但它任然有可能会导致有用的数据被淘汰,没用的数据迟迟不淘汰(如果策略使用得当的情况下这都是小概率事件)。
  如果我现在说有种机制,可以让你Cache里不用的key数据自动清理掉,用的还留着,没有误杀也没有漏杀你信不信!没错WeakHashMap就是能实现这种功能的东西,这也是它和普通的HashMap不同的地方——它有自清理的机制。
  如果让你实现一种自清理的HashMap,你怎么做? 我的做法肯定是想办法先知道某个Key肯定没有在用了,然后清理到HashMap中对应的K-V。在JVM里一个对象没用了是指没有任何其他有用对象直接或者间接执行它,具体点就是在GC过程中它是GCRoots不可达的。 Jvm提供了一种机制能让我们感知到一个对象是否已经变成了垃圾对象,这就是WeakReference,不了解WeakReference的可以看下我上一篇介绍博客Java弱引用(WeakReferences)。
  某个WeakReference对象所指向的对象如果被判定为垃圾对象,Jvm会将该WeakReference对象放到一个ReferenceQueue里,我们只要看下这个Queue里的内容就知道某个对象还有没有用了。 WeakHashMap就是这么做的,所以这里的Weak是指WeakReference。接下来让我们看下它的代码,看它具体是怎么实现的。
  

源码分析

    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;

  和普通HashMap一样,WeakHashMap也有一些默认值,比如默认容量是16,最大容量2^30,使用超过75%它就会自动扩容。

Entry

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

        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;
        }
        /*
        * 其他代码  
        */
}

  它的Entry和普通HashMap的Entry最大的不同是它继承了WeakReference,然后把Key做成了弱引用(注意只有Key没有Value),然后传入了一个ReferenceQueue,这就让它能在某个key失去所有强引用的时候感知到。
  

赞(0) 打赏
未经允许不得转载:XINDOO » Java WeakHashMap
描述文字

评论 抢沙发

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫