|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
微软什么都提供了。你可以试想一下,如果你是新手,你是希望你点一下按钮程序就能运行那,还是想自己一点一点的组织结构,然后打包发部,调错再打包......
这一章,我们对WeakHashMap举行进修。
我们先对WeakHashMap有个全体熟悉,然后再进修它的源码,最初再经由过程实例来学会利用WeakHashMap。
第1部分WeakHashMap先容
WeakHashMap简介
WeakHashMap承继于AbstractMap,完成了Map接口。
和HashMap一样,WeakHashMap也是一个散列表,它存储的内容也是键值对(key-value)映照,并且键和值都能够是null。
不外WeakHashMap的键是“弱键”。在WeakHashMap中,当某个键不再一般利用时,会被从WeakHashMap中被主动移除。更准确地说,关于一个给定的键,其映照的存在其实不制止渣滓接纳器对该键的抛弃,这就使该键成为可停止的,被停止,然后被接纳。某个键被停止时,它对应的键值对也就从映照中无效地移除。
这个“弱键”的道理呢?大抵上就是,经由过程WeakReference和ReferenceQueue完成的。WeakHashMap的key是“弱键”,便是WeakReference范例的;ReferenceQueue是一个行列,它会保留被GC接纳的“弱键”。完成步骤是:
(01)新建WeakHashMap,将“键值对”增加到WeakHashMap中。
实践上,WeakHashMap是经由过程数组table保留Entry(键值对);每个Entry实践上是一个单向链表,即Entry是键值对链表。
(02)当某“弱键”不再被别的对象援用,并被GC接纳时。在GC接纳该“弱键”时,这个“弱键”也同时会被增加到ReferenceQueue(queue)行列中。
(03)当下一次我们必要操纵WeakHashMap时,会先同步table和queue。table中保留了全体的键值对,而queue中保留被GC接纳的键值对;同步它们,就是删除table中被GC接纳的键值对。
这就是“弱键”怎样被主动从WeakHashMap中删除的步骤了。
和HashMap一样,WeakHashMap是分歧步的。可使用Collections.synchronizedMap办法来机关同步的WeakHashMap。
WeakHashMap的承继干系以下- java.lang.Object
- java.util.AbstractMap<K,V>
- java.util.WeakHashMap<K,V>
- publicclassWeakHashMap<K,V>
- extendsAbstractMap<K,V>
- implementsMap<K,V>{}
复制代码 WeakHashMap与Map干系以下图:
WeakHashMap的机关函数
WeakHashMap共有4个机关函数,以下:- //默许机关函数。
- WeakHashMap()
- //指定“容量巨细”的机关函数
- WeakHashMap(intcapacity)
- //指定“容量巨细”和“加载因子”的机关函数
- WeakHashMap(intcapacity,floatloadFactor)
- //包括“子Map”的机关函数
- WeakHashMap(Map<?extendsK,?extendsV>map)
复制代码 WeakHashMap的API- voidclear()
- Objectclone()
- booleancontainsKey(Objectkey)
- booleancontainsValue(Objectvalue)
- Set<Entry<K,V>>entrySet()
- Vget(Objectkey)
- booleanisEmpty()
- Set<K>keySet()
- Vput(Kkey,Vvalue)
- voidputAll(Map<?extendsK,?extendsV>map)
- Vremove(Objectkey)
- intsize()
- Collection<V>values()
复制代码
第2部分WeakHashMap源码剖析
上面对WeakHashMap的源码举行申明- packagejava.util;
- importjava.lang.ref.WeakReference;
- importjava.lang.ref.ReferenceQueue;
- publicclassWeakHashMap<K,V>
- extendsAbstractMap<K,V>
- implementsMap<K,V>{
- //默许的初始容量是16,必需是2的幂。
- privatestaticfinalintDEFAULT_INITIAL_CAPACITY=16;
- //最年夜容量(必需是2的幂且小于2的30次方,传进容量过上将被这个值交换)
- privatestaticfinalintMAXIMUM_CAPACITY=1<<30;
- //默许加载因子
- privatestaticfinalfloatDEFAULT_LOAD_FACTOR=0.75f;
- //存储数据的Entry数组,长度是2的幂。
- //WeakHashMap是接纳拉链法完成的,每个Entry实质上是一个单向链表
- privateEntry[]table;
- //WeakHashMap的巨细,它是WeakHashMap保留的键值对的数目
- privateintsize;
- //WeakHashMap的阈值,用于判别是不是必要调剂WeakHashMap的容量(threshold=容量*加载因子)
- privateintthreshold;
- //加载因籽实际巨细
- privatefinalfloatloadFactor;
- //queue保留的是“已被GC扫除”的“弱援用的键”。
- //弱援用和ReferenceQueue是团结利用的:假如弱援用所援用的对象被渣滓接纳,Java假造机就会把这个弱援用到场到与之联系关系的援用行列中
- privatefinalReferenceQueue<K>queue=newReferenceQueue<K>();
- //WeakHashMap被改动的次数
- privatevolatileintmodCount;
- //指定“容量巨细”和“加载因子”的机关函数
- publicWeakHashMap(intinitialCapacity,floatloadFactor){
- if(initialCapacity<0)
- thrownewIllegalArgumentException("IllegalInitialCapacity:"+
- initialCapacity);
- //WeakHashMap的最年夜容量只能是MAXIMUM_CAPACITY
- if(initialCapacity>MAXIMUM_CAPACITY)
- initialCapacity=MAXIMUM_CAPACITY;
- if(loadFactor<=0||Float.isNaN(loadFactor))
- thrownewIllegalArgumentException("IllegalLoadfactor:"+
- loadFactor);
- //找出“年夜于initialCapacity”的最小的2的幂
- intcapacity=1;
- while(capacity<initialCapacity)
- capacity<<=1;
- //创立Entry数组,用来保留数据
- table=newEntry[capacity];
- //设置“加载因子”
- this.loadFactor=loadFactor;
- //设置“WeakHashMap阈值”,当WeakHashMap中存储数据的数目到达threshold时,就必要将WeakHashMap的容量更加。
- threshold=(int)(capacity*loadFactor);
- }
- //指定“容量巨细”的机关函数
- publicWeakHashMap(intinitialCapacity){
- this(initialCapacity,DEFAULT_LOAD_FACTOR);
- }
- //默许机关函数。
- publicWeakHashMap(){
- this.loadFactor=DEFAULT_LOAD_FACTOR;
- threshold=(int)(DEFAULT_INITIAL_CAPACITY);
- table=newEntry[DEFAULT_INITIAL_CAPACITY];
- }
- //包括“子Map”的机关函数
- publicWeakHashMap(Map<?extendsK,?extendsV>m){
- this(Math.max((int)(m.size()/DEFAULT_LOAD_FACTOR)+1,16),
- DEFAULT_LOAD_FACTOR);
- //将m中的全体元素逐一增加到WeakHashMap中
- putAll(m);
- }
- //键为null的mask值。
- //由于WeakReference中同意“null的key”,若间接拔出“null的key”,将其看成弱援用时,会被删除。
- //因而,这里关于“key为null”的清空,都一致交换为“key为NULL_KEY”,“NULL_KEY”是“静态的final常量”。
- privatestaticfinalObjectNULL_KEY=newObject();
- //对“null的key”举行特别处置
- privatestaticObjectmaskNull(Objectkey){
- return(key==null?NULL_KEY:key);
- }
- //复原对“null的key”的特别处置
- privatestatic<K>KunmaskNull(Objectkey){
- return(K)(key==NULL_KEY?null:key);
- }
- //判别“x”和“y”是不是相称
- staticbooleaneq(Objectx,Objecty){
- returnx==y||x.equals(y);
- }
- //前往索引值
- //h&(length-1)包管前往值的小于length
- staticintindexFor(inth,intlength){
- returnh&(length-1);
- }
- //清空table中无用键值对。道理以下:
- //(01)当WeakHashMap中某个“弱援用的key”因为没有再被援用而被GC发出时,
- //被接纳的“该弱援用key”也被会被增加到"ReferenceQueue(queue)"中。
- //(02)当我们实行expungeStaleEntries时,
- //就遍历"ReferenceQueue(queue)"中的一切key
- //然后就在“WeakReference的table”中删除与“ReferenceQueue(queue)中key”对应的键值对
- privatevoidexpungeStaleEntries(){
- Entry<K,V>e;
- while((e=(Entry<K,V>)queue.poll())!=null){
- inth=e.hash;
- inti=indexFor(h,table.length);
- Entry<K,V>prev=table[i];
- Entry<K,V>p=prev;
- while(p!=null){
- Entry<K,V>next=p.next;
- if(p==e){
- if(prev==e)
- table[i]=next;
- else
- prev.next=next;
- e.next=null;//HelpGC
- e.value=null;//""
- size--;
- break;
- }
- prev=p;
- p=next;
- }
- }
- }
- //猎取WeakHashMap的table(寄存键值对的数组)
- privateEntry[]getTable(){
- //删除table中“已被GC接纳的key对应的键值对”
- expungeStaleEntries();
- returntable;
- }
- //猎取WeakHashMap的实践巨细
- publicintsize(){
- if(size==0)
- return0;
- //删除table中“已被GC接纳的key对应的键值对”
- expungeStaleEntries();
- returnsize;
- }
- publicbooleanisEmpty(){
- returnsize()==0;
- }
- //猎取key对应的value
- publicVget(Objectkey){
- Objectk=maskNull(key);
- //猎取key的hash值。
- inth=HashMap.hash(k.hashCode());
- Entry[]tab=getTable();
- intindex=indexFor(h,tab.length);
- Entry<K,V>e=tab[index];
- //在“该hash值对应的链表”上查找“键值即是key”的元素
- while(e!=null){
- if(e.hash==h&&eq(k,e.get()))
- returne.value;
- e=e.next;
- }
- returnnull;
- }
- //WeakHashMap是不是包括key
- publicbooleancontainsKey(Objectkey){
- returngetEntry(key)!=null;
- }
- //前往“键为key”的键值对
- Entry<K,V>getEntry(Objectkey){
- Objectk=maskNull(key);
- inth=HashMap.hash(k.hashCode());
- Entry[]tab=getTable();
- intindex=indexFor(h,tab.length);
- Entry<K,V>e=tab[index];
- while(e!=null&&!(e.hash==h&&eq(k,e.get())))
- e=e.next;
- returne;
- }
- //将“key-value”增加到WeakHashMap中
- publicVput(Kkey,Vvalue){
- Kk=(K)maskNull(key);
- inth=HashMap.hash(k.hashCode());
- Entry[]tab=getTable();
- inti=indexFor(h,tab.length);
- for(Entry<K,V>e=tab[i];e!=null;e=e.next){
- //若“该key”对应的键值对已存在,则用新的value代替旧的value。然前进出!
- if(h==e.hash&&eq(k,e.get())){
- VoldValue=e.value;
- if(value!=oldValue)
- e.value=value;
- returnoldValue;
- }
- }
- //若“该key”对应的键值对不存在于WeakHashMap中,则将“key-value”增加到table中
- modCount++;
- Entry<K,V>e=tab[i];
- tab[i]=newEntry<K,V>(k,value,queue,h,e);
- if(++size>=threshold)
- resize(tab.length*2);
- returnnull;
- }
- //从头调剂WeakHashMap的巨细,newCapacity是调剂后的单元
- voidresize(intnewCapacity){
- Entry[]oldTable=getTable();
- intoldCapacity=oldTable.length;
- if(oldCapacity==MAXIMUM_CAPACITY){
- threshold=Integer.MAX_VALUE;
- return;
- }
- //新建一个newTable,将“旧的table”的全体元素增加到“新的newTable”中,
- //然后,将“新的newTable”赋值给“旧的table”。
- Entry[]newTable=newEntry[newCapacity];
- transfer(oldTable,newTable);
- table=newTable;
- if(size>=threshold/2){
- threshold=(int)(newCapacity*loadFactor);
- }else{
- //删除table中“已被GC接纳的key对应的键值对”
- expungeStaleEntries();
- transfer(newTable,oldTable);
- table=oldTable;
- }
- }
- //将WeakHashMap中的全体元素都增加到newTable中
- privatevoidtransfer(Entry[]src,Entry[]dest){
- for(intj=0;j<src.length;++j){
- Entry<K,V>e=src[j];
- src[j]=null;
- while(e!=null){
- Entry<K,V>next=e.next;
- Objectkey=e.get();
- if(key==null){
- e.next=null;//HelpGC
- e.value=null;//""
- size--;
- }else{
- inti=indexFor(e.hash,dest.length);
- e.next=dest[i];
- dest[i]=e;
- }
- e=next;
- }
- }
- }
- //将"m"的全体元素都增加到WeakHashMap中
- publicvoidputAll(Map<?extendsK,?extendsV>m){
- intnumKeysToBeAdded=m.size();
- if(numKeysToBeAdded==0)
- return;
- //盘算容量是不是充足,
- //若“以后实践容量<必要的容量”,则将容量x2。
- if(numKeysToBeAdded>threshold){
- inttargetCapacity=(int)(numKeysToBeAdded/loadFactor+1);
- if(targetCapacity>MAXIMUM_CAPACITY)
- targetCapacity=MAXIMUM_CAPACITY;
- intnewCapacity=table.length;
- while(newCapacity<targetCapacity)
- newCapacity<<=1;
- if(newCapacity>table.length)
- resize(newCapacity);
- }
- //将“m”中的元素逐一增加到WeakHashMap中。
- for(Map.Entry<?extendsK,?extendsV>e:m.entrySet())
- put(e.getKey(),e.getValue());
- }
- //删除“键为key”元素
- publicVremove(Objectkey){
- Objectk=maskNull(key);
- //猎取哈希值。
- inth=HashMap.hash(k.hashCode());
- Entry[]tab=getTable();
- inti=indexFor(h,tab.length);
- Entry<K,V>prev=tab[i];
- Entry<K,V>e=prev;
- //删除链表中“键为key”的元素
- //实质是“删除单向链表中的节点”
- while(e!=null){
- Entry<K,V>next=e.next;
- if(h==e.hash&&eq(k,e.get())){
- modCount++;
- size--;
- if(prev==e)
- tab[i]=next;
- else
- prev.next=next;
- returne.value;
- }
- prev=e;
- e=next;
- }
- returnnull;
- }
- //删除“键值对”
- Entry<K,V>removeMapping(Objecto){
- if(!(oinstanceofMap.Entry))
- returnnull;
- Entry[]tab=getTable();
- Map.Entryentry=(Map.Entry)o;
- Objectk=maskNull(entry.getKey());
- inth=HashMap.hash(k.hashCode());
- inti=indexFor(h,tab.length);
- Entry<K,V>prev=tab[i];
- Entry<K,V>e=prev;
- //删除链表中的“键值对e”
- //实质是“删除单向链表中的节点”
- while(e!=null){
- Entry<K,V>next=e.next;
- if(h==e.hash&&e.equals(entry)){
- modCount++;
- size--;
- if(prev==e)
- tab[i]=next;
- else
- prev.next=next;
- returne;
- }
- prev=e;
- e=next;
- }
- returnnull;
- }
- //清空WeakHashMap,将一切的元素设为null
- publicvoidclear(){
- while(queue.poll()!=null)
- ;
- modCount++;
- Entry[]tab=table;
- for(inti=0;i<tab.length;++i)
- tab[i]=null;
- size=0;
- while(queue.poll()!=null)
- ;
- }
- //是不是包括“值为value”的元素
- publicbooleancontainsValue(Objectvalue){
- //若“value为null”,则挪用containsNullValue()查找
- if(value==null)
- returncontainsNullValue();
- //若“value不为null”,则查找WeakHashMap中是不是有值为value的节点。
- Entry[]tab=getTable();
- for(inti=tab.length;i-->0;)
- for(Entrye=tab[i];e!=null;e=e.next)
- if(value.equals(e.value))
- returntrue;
- returnfalse;
- }
- //是不是包括null值
- privatebooleancontainsNullValue(){
- Entry[]tab=getTable();
- for(inti=tab.length;i-->0;)
- for(Entrye=tab[i];e!=null;e=e.next)
- if(e.value==null)
- returntrue;
- returnfalse;
- }
- //Entry是单向链表。
- //它是“WeakHashMap链式存储法”对应的链表。
- //它完成了Map.Entry接口,即完成getKey(),getValue(),setValue(Vvalue),equals(Objecto),hashCode()这些函数
- privatestaticclassEntry<K,V>extendsWeakReference<K>implementsMap.Entry<K,V>{
- privateVvalue;
- privatefinalinthash;
- //指向下一个节点
- privateEntry<K,V>next;
- //机关函数。
- Entry(Kkey,Vvalue,
- ReferenceQueue<K>queue,
- inthash,Entry<K,V>next){
- super(key,queue);
- this.value=value;
- this.hash=hash;
- this.next=next;
- }
- publicKgetKey(){
- returnWeakHashMap.<K>unmaskNull(get());
- }
- publicVgetValue(){
- returnvalue;
- }
- publicVsetValue(VnewValue){
- VoldValue=value;
- value=newValue;
- returnoldValue;
- }
- //判别两个Entry是不是相称
- //若两个Entry的“key”和“value”都相称,则前往true。
- //不然,前往false
- publicbooleanequals(Objecto){
- if(!(oinstanceofMap.Entry))
- returnfalse;
- Map.Entrye=(Map.Entry)o;
- Objectk1=getKey();
- Objectk2=e.getKey();
- if(k1==k2||(k1!=null&&k1.equals(k2))){
- Objectv1=getValue();
- Objectv2=e.getValue();
- if(v1==v2||(v1!=null&&v1.equals(v2)))
- returntrue;
- }
- returnfalse;
- }
- //完成hashCode()
- publicinthashCode(){
- Objectk=getKey();
- Objectv=getValue();
- return((k==null?0:k.hashCode())^
- (v==null?0:v.hashCode()));
- }
- publicStringtoString(){
- returngetKey()+"="+getValue();
- }
- }
- //HashIterator是WeakHashMap迭代器的笼统出来的父类,完成了大众了函数。
- //它包括“key迭代器(KeyIterator)”、“Value迭代器(ValueIterator)”和“Entry迭代器(EntryIterator)”3个子类。
- privateabstractclassHashIterator<T>implementsIterator<T>{
- //以后索引
- intindex;
- //以后元素
- Entry<K,V>entry=null;
- //上一次前往元素
- Entry<K,V>lastReturned=null;
- //expectedModCount用于完成fast-fail机制。
- intexpectedModCount=modCount;
- //下一个键(强援用)
- ObjectnextKey=null;
- //以后键(强援用)
- ObjectcurrentKey=null;
- //机关函数
- HashIterator(){
- index=(size()!=0?table.length:0);
- }
- //是不是存鄙人一个元素
- publicbooleanhasNext(){
- Entry[]t=table;
- //一个Entry就是一个单向链表
- //若该Entry的下一个节点不为空,就将next指向下一个节点;
- //不然,将next指向下一个链表(也是下一个Entry)的不为null的节点。
- while(nextKey==null){
- Entry<K,V>e=entry;
- inti=index;
- while(e==null&&i>0)
- e=t[--i];
- entry=e;
- index=i;
- if(e==null){
- currentKey=null;
- returnfalse;
- }
- nextKey=e.get();//holdontokeyinstrongref
- if(nextKey==null)
- entry=entry.next;
- }
- returntrue;
- }
- //猎取下一个元素
- protectedEntry<K,V>nextEntry(){
- if(modCount!=expectedModCount)
- thrownewConcurrentModificationException();
- if(nextKey==null&&!hasNext())
- thrownewNoSuchElementException();
- lastReturned=entry;
- entry=entry.next;
- currentKey=nextKey;
- nextKey=null;
- returnlastReturned;
- }
- //删除以后元素
- publicvoidremove(){
- if(lastReturned==null)
- thrownewIllegalStateException();
- if(modCount!=expectedModCount)
- thrownewConcurrentModificationException();
- WeakHashMap.this.remove(currentKey);
- expectedModCount=modCount;
- lastReturned=null;
- currentKey=null;
- }
- }
- //value的迭代器
- privateclassValueIteratorextendsHashIterator<V>{
- publicVnext(){
- returnnextEntry().value;
- }
- }
- //key的迭代器
- privateclassKeyIteratorextendsHashIterator<K>{
- publicKnext(){
- returnnextEntry().getKey();
- }
- }
- //Entry的迭代器
- privateclassEntryIteratorextendsHashIterator<Map.Entry<K,V>>{
- publicMap.Entry<K,V>next(){
- returnnextEntry();
- }
- }
- //WeakHashMap的Entry对应的汇合
- privatetransientSet<Map.Entry<K,V>>entrySet=null;
- //前往“key的汇合”,实践上前往一个“KeySet对象”
- publicSet<K>keySet(){
- Set<K>ks=keySet;
- return(ks!=null?ks:(keySet=newKeySet()));
- }
- //Key对应的汇合
- //KeySet承继于AbstractSet,申明该汇合中没有反复的Key。
- privateclassKeySetextendsAbstractSet<K>{
- publicIterator<K>iterator(){
- returnnewKeyIterator();
- }
- publicintsize(){
- returnWeakHashMap.this.size();
- }
- publicbooleancontains(Objecto){
- returncontainsKey(o);
- }
- publicbooleanremove(Objecto){
- if(containsKey(o)){
- WeakHashMap.this.remove(o);
- returntrue;
- }
- else
- returnfalse;
- }
- publicvoidclear(){
- WeakHashMap.this.clear();
- }
- }
- //前往“value汇合”,实践上前往的是一个Values对象
- publicCollection<V>values(){
- Collection<V>vs=values;
- return(vs!=null?vs:(values=newValues()));
- }
- //“value汇合”
- //Values承继于AbstractCollection,分歧于“KeySet承继于AbstractSet”,
- //Values中的元素可以反复。由于分歧的key能够指向不异的value。
- privateclassValuesextendsAbstractCollection<V>{
- publicIterator<V>iterator(){
- returnnewValueIterator();
- }
- publicintsize(){
- returnWeakHashMap.this.size();
- }
- publicbooleancontains(Objecto){
- returncontainsValue(o);
- }
- publicvoidclear(){
- WeakHashMap.this.clear();
- }
- }
- //前往“WeakHashMap的Entry汇合”
- //它实践是前往一个EntrySet对象
- publicSet<Map.Entry<K,V>>entrySet(){
- Set<Map.Entry<K,V>>es=entrySet;
- returnes!=null?es:(entrySet=newEntrySet());
- }
- //EntrySet对应的汇合
- //EntrySet承继于AbstractSet,申明该汇合中没有反复的EntrySet。
- privateclassEntrySetextendsAbstractSet<Map.Entry<K,V>>{
- publicIterator<Map.Entry<K,V>>iterator(){
- returnnewEntryIterator();
- }
- //是不是包括“值(o)”
- publicbooleancontains(Objecto){
- if(!(oinstanceofMap.Entry))
- returnfalse;
- Map.Entrye=(Map.Entry)o;
- Objectk=e.getKey();
- Entrycandidate=getEntry(e.getKey());
- returncandidate!=null&&candidate.equals(e);
- }
- //删除“值(o)”
- publicbooleanremove(Objecto){
- returnremoveMapping(o)!=null;
- }
- //前往WeakHashMap的巨细
- publicintsize(){
- returnWeakHashMap.this.size();
- }
- //清空WeakHashMap
- publicvoidclear(){
- WeakHashMap.this.clear();
- }
- //拷贝函数。将WeakHashMap中的全体元素都拷贝到List中
- privateList<Map.Entry<K,V>>deepCopy(){
- List<Map.Entry<K,V>>list=newArrayList<Map.Entry<K,V>>(size());
- for(Map.Entry<K,V>e:this)
- list.add(newAbstractMap.SimpleEntry<K,V>(e));
- returnlist;
- }
- //前往Entry对应的Object[]数组
- publicObject[]toArray(){
- returndeepCopy().toArray();
- }
- //前往Entry对应的T[]数组(T[]我们新建数组时,界说的数组范例)
- public<T>T[]toArray(T[]a){
- returndeepCopy().toArray(a);
- }
- }
- }
复制代码 检察本栏目更多出色内容:http://www.bianceng.cn/Programming/Java/
申明:
<p>
对于一个大型项目,如果用java来作,可能需要9个月,并且可能需要翻阅10本以上的书,但如果用ruby来作,3个月,3本书就足够了,而.net也不过3,4本书足以,这就是区别。 |
|