WeakHashMap

http://www.cnblogs.com/jisheng/archive/2011/12/02/2271862.html

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. }  
 

 在《Effective Java》一书中第六条,消除陈旧对象时,提到了weakHashMap,看了下还是适用的,即在我们使用短时间内就过期的缓存时最好使用 weakHashMap,它包含了一个自动调用的方法expungeStaleEntries,这样就会在值被引用后直接执行这个隐含的方法,将不用的键 清除掉。

 测试了一下

Java代码  收藏代码
  1. package com.alibaba.itbu.job.billing;  
  2.   
  3. import java.util.Map;  
  4. import java.util.WeakHashMap;  
  5.   
  6. public class WeakHashMapTest {  
  7.     static Map wMap = new WeakHashMap();  
  8.     public static void init(){  
  9.         wMap.put("1""ding");  
  10.         wMap.put("2""job");  
  11.     }  
  12.     public static void testWeakHashMap(){  
  13.   
  14.         System.out.println("first get:"+wMap.get("1"));  
  15.         try {  
  16.             Thread.sleep(5000);  
  17.         } catch (InterruptedException e) {  
  18.             // TODO Auto-generated catch block  
  19.             e.printStackTrace();  
  20.         }  
  21.         System.out.println("next get:"+wMap.get("1"));  
  22.     }  
  23.     public static void main(String[] args) {  
  24.         testWeakHashMap();  
  25.     }  
  26. }  

 

 

上面例子, 第一次执行时要初始化,然后在5s内是不会清除的,大概在10几秒时会清除

 

第一次执行

first get:ding

next get:ding

 

过一会再执行:

first get:null
next get:null

 

这时候已经被清除

同样,没有调用任何赋值方法的情况下,在一段时间后 size 方法也可能返回较小的值,对于 isEmpty 方法,返回false,然后返回 true,对于给定的键,containsKey 方法返回 true 然后返回 false,对于给定的键,get 方法返回一个值,但接着返回 null,对于以前出现在映射中的键,put 方法返回 null,而 remove 方法返回 false,对于键集、值集、项集进行的检查,生成的元素数量越来越少。

 

 

注意:WeakHashMap并不是你啥也干他就能自动释放内部不用的对象的,而是在你访问它的内容的时候释放内部不用的对象。这两句话看似区别不大,但是有时候一个小小的区别就会要了命的。就是说你只put 了压根没有get过,这个值是永远都存在的

 

 

 

我们也可以看下这个移除键值的实现

Java代码  收藏代码
  1. private void expungeStaleEntries() {  
  2.     Entry<K,V> e;  
  3.         while ( (e = (Entry<K,V>) queue.poll()) != null) {  
  4.             int h = e.hash;  
  5.             int i = indexFor(h, table.length);  
  6.   
  7.             Entry<K,V> prev = table[i];  
  8.             Entry<K,V> p = prev;  
  9.             while (p != null) {  
  10.                 Entry<K,V> next = p.next;  
  11.                 if (p == e) {  
  12.                     if (prev == e)  
  13.                         table[i] = next;  
  14.                     else  
  15.                         prev.next = next;  
  16.                     e.next = null;  // Help GC  
  17.                     e.value = null//  "   "  
  18.                     size--;  
  19.                     break;  
  20.                 }  
  21.                 prev = p;  
  22.                 p = next;  
  23.             }  
  24.         }  
  25.     }  

 

 

就是使用了链表,找到这个hash值  将这个hash值移除 size减少

posted on 2014-04-03 14:24  ttjava  阅读(378)  评论(0编辑  收藏  举报