现在的位置: 首页 > 综合 > 正文

WeakHashMap和HashMap的区别

2013年12月10日 ⁄ 综合 ⁄ 共 3035字 ⁄ 字号 评论关闭

WeakHashMap,此种Map的特点是,当除了自身有对key的引用外,此key没有其他引用那么此map会自动丢弃此值,

见实例:此例子中声明了两个Map对象,一个是HashMap,一个是WeakHashMap,同时向两个map中放入a、b两个对象,当HashMap  remove掉a 并且将a、b都指向null时,WeakHashMap中的a将自动被回收掉。出现这个状况的原因是,对于a对象而言,当HashMap  remove掉并且将a指向null后,除了WeakHashMap中还保存a外已经没有指向a的指针了,所以WeakHashMap会自动舍弃掉a,而对于b对象虽然指向了null,但HashMap中还有指向b的指针,所以

WeakHashMap将会保留

Java代码  收藏代码
  1. package test;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Iterator;  
  5. import java.util.Map;  
  6. import java.util.WeakHashMap;  
  7.   
  8. public class Test {  
  9.     public static void main(String[] args) throws Exception {  
  10.         String a = new String("a");  
  11.         String b = new String("b");  
  12.         Map weakmap = new WeakHashMap();  
  13.         Map map = new HashMap();  
  14.         map.put(a, "aaa");  
  15.         map.put(b, "bbb");  
  16.   
  17.           
  18.         weakmap.put(a, "aaa");  
  19.         weakmap.put(b, "bbb");  
  20.           
  21.         map.remove(a);  
  22.           
  23.         a=null;  
  24.         b=null;  
  25.           
  26.         System.gc();  
  27.         Iterator i = map.entrySet().iterator();  
  28.         while (i.hasNext()) {  
  29.             Map.Entry en = (Map.Entry)i.next();  
  30.             System.out.println("map:"+en.getKey()+":"+en.getValue());  
  31.         }  
  32.   
  33.         Iterator j = weakmap.entrySet().iterator();  
  34.         while (j.hasNext()) {  
  35.             Map.Entry en = (Map.Entry)j.next();  
  36.             System.out.println("weakmap:"+en.getKey()+":"+en.getValue());  
  37.               
  38.         }  
  39.     }  
  40.   
  41.       
  42. }  

 

来自:

http://mzlly999.iteye.com/blog/1126049

==================================================

先把问题说清楚:

WeakHashMap是主要通过expungeStaleEntries这个函数的来实现移除其内部不用的条目从而达到的自动释放内存的目的的.基本上只要对WeakHashMap的内容进行访问就会调用这个函数,从而达到清除其内部不在为外部引用的条目。但是如果预先生成了WeakHashMap,而在GC以前又不曾访问该WeakHashMap,那不是就不能释放内存了吗?

对应的两个测试案例:

WeakHashMapTest1:

public class WeakHashMapTest1 {
public static void main(String[] args) throws Exception {
List<WeakHashMap<byte[][], byte[][]>> maps = new ArrayList<WeakHashMap<byte[][], byte[][]>>();
for (int i = 0; i < 1000; i++) {
WeakHashMap<byte[][], byte[][]> d = new WeakHashMap<byte[][], byte[][]>();
d.put(new byte[1000][1000], new byte[1000][1000]);
maps.add(d);
System.gc();
System.err.println(i);
}
}
}

由于Java默认内存是64M,所以再不改变内存参数的情况下,该测试跑不了几步循环就内存溢出了。果不其然,WeakHashMap这个时候并没有自动帮我们释放不用的内存。

WeakHashMapTest2:

public class WeakHashMapTest2 {
public static void main(String[] args) throws Exception {
List<WeakHashMap<byte[][], byte[][]>> maps = new ArrayList<WeakHashMap<byte[][], byte[][]>>();
for (int i = 0; i < 1000; i++) {
WeakHashMap<byte[][], byte[][]> d = new WeakHashMap<byte[][], byte[][]>();
d.put(new byte[1000][1000], new byte[1000][1000]);
maps.add(d);
System.gc();
System.err.println(i);
for (int j = 0; j < i; j++) {
System.err.println(j + " size" + maps.get(j).size());
}
}
}
}

这次测试输出正常,不在出现内存溢出问题.

总结来说:WeakHashMap并不是你啥也干他就能自动释放内部不用的对象的,而是在你访问它的内容的时候释放内部不用的对象

问题讲清楚了,现在我们来梳理一下.了解清楚其中的奥秘.

WeakHashMap实现弱引用,是因为它的Entry<K,V>是继承自WeakReference<K>

WeakHashMap$Entry<K,V>的类定义及构造函数里面是这样写的

private static class Entry<K,V> 
extends WeakReference<K>
implements Map.Entry<K,V> Entry(K key, V value, ReferenceQueue<K> queue,int hash, Entry<K,V> next) {
super(key, queue);
this.value = value;
this.hash = hash;
this.next = next;
}

请注意它构造父类的语句:“super(key,
queue);”
,传入的是key,因此

抱歉!评论已关闭.