Java 集合 - WeakHashMap
[TOC]
JDK版本:JDK 1.8.0_110
1. 概述
在Java集合框架系列文章的最后,笔者打算介绍一个特殊的成员: WeakHashMap,从名字可以看出它是某种 Map。它的特殊之处在于 WeakHashMap 里的entry
可能会被GC自动删除,即使程序员没有调用remove()
或者clear()
方法。
更直观的说,当使用 WeakHashMap 时,即使没有显示的添加或删除任何元素,也可能发生如下情况:
调用两次
size()
方法返回不同的值;两次调用
isEmpty()
方法,第一次返回false
,第二次返回true
;两次调用
containsKey()
方法,第一次返回true
,第二次返回false
,尽管两次使用的是同一个key
;两次调用
get()
方法,第一次返回一个value
,第二次返回null
,尽管两次使用的是同一个对象。
遇到这么奇葩的现象,你是不是觉得使用者一定会疯掉? 其实不然,WeakHashMap 的这个特点特别适用于需要缓存的场景。在缓存场景下,由于内存是有限的,不能缓存所有对象;对象缓存命中可以提高系统效率,但缓存MISS也不会造成错误,因为可以通过计算重新得到。
要明白 WeakHashMap 的工作原理,还需要引入一个概念 : 弱引用(WeakReference)。我们都知道Java中内存是通过GC自动管理的,GC会在程序运行过程中自动判断哪些对象是可以被回收的,并在合适的时机进行内存释放。GC判断某个对象是否可被回收的依据是,是否有有效的引用指向该对象。如果没有有效引用指向该对象(基本意味着不存在访问该对象的方式),那么该对象就是可回收的。这里的**“有效引用”并不包括弱引用**。也就是说,虽然弱引用可以用来访问对象,但进行垃圾回收时弱引用并不会被考虑在内,仅有弱引用指向的对象仍然会被GC回收。
WeakHashMap 内部是通过弱引用来管理entry
的,弱引用的特性对应到 WeakHashMap 上意味着什么呢?将一对key, value
放入到 WeakHashMap 里并不能避免该key
值被GC回收,除非在 WeakHashMap 之外还有对该key
的强引用。
关于强引用,弱引用等概念以后再具体讲解,这里只需要知道Java中引用也是分种类的,并且不同种类的引用对GC的影响不同就够了。
2. 具体实现
WeakHashMap的存储结构类似于Map - HashSet & HashMap 源码解析,这里不再赘述。
关于强弱引用的管理方式,博主将会另开专题单独讲解。
3. Weak HashSet?
如果你看过前几篇关于 Map 和 Set 的讲解,一定会问: 既然有 WeakHashMap,是否有 WeekHashSet 呢? 答案是没有:( 。不过Java Collections工具类给出了解决方案,Collections.newSetFromMap(Map<E,Boolean> map)
方法可以将任何 Map包装成一个Set。通过如下方式可以快速得到一个 Weak HashSet:
不出你所料,newSetFromMap()
方法只是对传入的 Map做了简单包装:
4. 参考
浅谈WeakHashMap https://www.cnblogs.com/CarpenterLee/p/5544598.html
最后更新于