WeakHashMap
WeakHashMap 特殊之处在于 WeakHashMap 里的entry可能会被垃圾回收器自动删除,也就是说即使你没有调用remove()【remove()会把对应的entry清除掉】或者clear()方法,它的entry也可能会慢慢变少。所以多次调用比如isEmpty,containsKey,size等方法时可能会返回不同的结果。
WeakHashMap中的key是间接保存在弱引用中的,所以当key没有被继续使用时,就可能会在GC的时候被回收掉(回收掉对应的entry)。
它的Entry和普通HashMap的Entry最大的不同是它继承了WeakReference,然后把Key做成了弱引用(注意只有Key没有Value),然后传入了一个ReferenceQueue,这就让它能在某个key失去所有强引用的时候感知到。
HashMap中想要清除无用的对象
Hashmap的remove()方法会把对应的entry<k,v>删除掉,这样子对象引用(k和v)就没了;
当对象没用的时候,即其他的地方没有指向对象的引用时,想要把对象回收掉,那就需要我们手动将hashmap中存的entry删掉,这样对象才可以删掉
public void mapTest(){
Integer t1 = 1;
Integer t2 = 2;
HashMap<Integer,Integer> map = new HashMap<>();
map.put(t1,1);
map.put(t2,2);
// t1指向null了,对象t1无用了,但是map里仍然存着对象引用,所以不会清除对象,造成内存泄漏
t1 = null;
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
for(Map.Entry<Integer,Integer> entry : entries){
System.out.println(entry.getKey() + "***" + entry.getValue());
}
}
GC不会清楚对象
weakHashMap的使用
WeakHashMap使用像map一样用,会自动把key变成对应的弱引用;
但是不要在其他地方引用key,如果存放在WeakHashMap中的key都存在强引用,那么WeakHashMap就会退化为HashMap。
public void mapTest(){
Integer t1 = 1;
Integer t2 = 2;
WeakHashMap<Integer,Integer> map = new WeakHashMap<>();
map.put(t1,1);
map.put(t2,2);
// t1指向null了,对象t1无用了,map里存的为弱引用
t1 = null;
// 一段时间GC后,下面就不在输出t1了
System.gc();
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
for(Map.Entry<Integer,Integer> entry : entries){
System.out.println(entry.getKey() + "***" + entry.getValue());
}
}
上面例子有问题
Integer类型 默认-128—127存储在方法区,之外数据存储在堆中。
Integer对象t1不会被gc掉,存大于127的会被gc掉,或者直接new一个Integer对象也会被GC掉
弱引用的使用
定义弱引用对象
productA = new Product(...);
WeakReference<Product> weakProductA = new WeakReference<>(productA);
若引用对象weakProductA就指向了Product对象productA。那么我们怎么通过weakProduct获取它所指向的Product对象productA呢?
Product product = weakProductA.get();
hashmap的值可否为null
HashMap对象的key、value值均可为null。
HahTable对象的key、value值均不可为null。