版权声明:欢迎转载,请注明作者和出处 https://blog.csdn.net/baichoufei90/article/details/83551202
Java学习-容器-WeakHashMap
0x01 摘要
本文简要介绍弱引用的典型应用-WeakHashMap。
0x02 基础概念
WeakHashMap
是一个特殊的map,有着弱引用的key。也就是说,当某个key没有再被正常使用时,WeakHashMap中的这个key对应的entry
会被自动移除。更准确的说,一个拥有一个指定的key的mapping映射存在也不能阻止该key被GC回收。当一个key被GC回收掉后,他的entry会从该Map中被高效移除掉。这一点是WeakHashMap与其他map最大的不同之处。
当使用 WeakHashMap 时,即使没有显示的添加或删除任何元素,即使你使用了synchronize获取改weakHashMap实例对象锁,也可能发生如下情况:
- 调用两次size()方法返回不同的值;
- 两次调用isEmpty()方法,第一次返回false,第二次返回true;
- 两次调用containsKey()方法,第一次返回true,第二次返回false,尽管两次使用的是同一个key;
- 两次调用get()方法,第一次返回一个value,第二次返回null,尽管两次使用的是同一个对象。
0x03 容器特点
WeakHashMap特点如下:
- key为弱引用,所以可能随时从map中移除对应的entry
- 新增元素时 key 和 value 都能为
null
- 非线程安全,必须用
Collections.synchronizedMap(new WeakHashMap<>())
- 主要适用于那些key使用
==
来判断是否相等的对象。一旦该key被GC回收那么不可能再重造一个完全相同对象,也就不能再用相同对象key到WeakHashMap中查找导致到结果 - value为强引用。注意一定不能让value直接或间接引用他自己的key,否则会让key永不删除
- 由此类的所有“集合视图方法”返回的集合的
iterator()
方法返回的迭代器有快速失败fail-fast
特性:即当iterator创建后,该map发生了结构性变化,那么调用除了迭代器自身的remove
方法外的任何方法都会导致抛出ConcurrentModificationException
。但要注意,这个特性并不是百分百可靠的。
0x04 使用示例
import java.util.Iterator;
import java.util.WeakHashMap;
/**
* Created by chengc on 2018/10/30.
*/
public class WeakHashMapTest2 {
public static void main(String[] args) {
WeakHashMap weakHashMap = new WeakHashMap<String, Object>();
final int SIZE = 10;
String[] str = new String[SIZE];
for (int i = 0; i < SIZE; i++){
String key = String.valueOf(i);
String value = String.valueOf(i);
// 保留偶数到String[],也就是偶数位有强引用
if(i % 2 == 0){
str[i] = key;
}
// 全部数字放入weakHashMap
weakHashMap.put(key, value);
}
// 显示调用gc
System.gc();
// 遍历weakHashMap
Iterator iter = weakHashMap.keySet().iterator();
while(iter.hasNext()){
System.out.println(weakHashMap.get(iter.next()));
}
}
}
以上例子中,因为将偶数放入String数组中,所以就有相应的强引用,其他奇数都是弱引用。
在gc过后,遍历结果就只剩偶数了,奇数都因为只有弱引用key而被GC干掉了。