C#创建安全的字典(Dictionary)存储结构
在上面介绍过栈(Stack)的存储结构,接下来介绍另一种存储结构字典(Dictionary)。字典(Dictionary)里面的每一个元素都是一个键值对(由二个元素组成:键和值)键必须是唯一的,而值不需要唯一的,键和值都可以是任何类型。字典(Dictionary)是常用于查找和排序的列表。
接下来看一下Dictionary的部分方法和类的底层实现代码:
1.Add:将指定的键和值添加到字典中。
publicvoidAdd(TKeykey,TValuevalue){ Insert(key,value,true); } privatevoidInsert(TKeykey,TValuevalue,booladd){ if(key==null){ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } if(buckets==null)Initialize(0); inthashCode=comparer.GetHashCode(key)&0x7FFFFFFF; inttargetBucket=hashCode%buckets.Length; #ifFEATURE_RANDOMIZED_STRING_HASHING intcollisionCount=0; #endif for(inti=buckets[targetBucket];i>=0;i=entries[i].next){ if(entries[i].hashCode==hashCode&&comparer.Equals(entries[i].key,key)){ if(add){ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); } entries[i].value=value; version++; return; } #ifFEATURE_RANDOMIZED_STRING_HASHING collisionCount++; #endif } intindex; if(freeCount>0){ index=freeList; freeList=entries[index].next; freeCount--; } else{ if(count==entries.Length) { Resize(); targetBucket=hashCode%buckets.Length; } index=count; count++; } entries[index].hashCode=hashCode; entries[index].next=buckets[targetBucket]; entries[index].key=key; entries[index].value=value; buckets[targetBucket]=index; version++; #ifFEATURE_RANDOMIZED_STRING_HASHING if(collisionCount>HashHelpers.HashCollisionThreshold&&HashHelpers.IsWellKnownEqualityComparer(comparer)) { comparer=(IEqualityComparer<TKey>)HashHelpers.GetRandomizedEqualityComparer(comparer); Resize(entries.Length,true); } #endif }
2.Clear():从Dictionary<TKey,TValue>中移除所有的键和值。
publicvoidClear(){ if(count>0){ for(inti=0;i<buckets.Length;i++)buckets[i]=-1; Array.Clear(entries,0,count); freeList=-1; count=0; freeCount=0; version++; } }
3.Remove():从Dictionary<TKey,TValue>中移除所指定的键的值。
publicboolRemove(TKeykey){ if(key==null){ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } if(buckets!=null){ inthashCode=comparer.GetHashCode(key)&0x7FFFFFFF; intbucket=hashCode%buckets.Length; intlast=-1; for(inti=buckets[bucket];i>=0;last=i,i=entries[i].next){ if(entries[i].hashCode==hashCode&&comparer.Equals(entries[i].key,key)){ if(last<0){ buckets[bucket]=entries[i].next; } else{ entries[last].next=entries[i].next; } entries[i].hashCode=-1; entries[i].next=freeList; entries[i].key=default(TKey); entries[i].value=default(TValue); freeList=i; freeCount++; version++; returntrue; } } } returnfalse; }
4.GetEnumerator():返回循环访问Dictionary<TKey,TValue>的枚举器。
publicEnumeratorGetEnumerator(){ returnnewEnumerator(this,Enumerator.KeyValuePair); } [Serializable] publicstructEnumerator:IEnumerator<KeyValuePair<TKey,TValue>>, IDictionaryEnumerator { privateDictionary<TKey,TValue>dictionary; privateintversion; privateintindex; privateKeyValuePair<TKey,TValue>current; privateintgetEnumeratorRetType;//WhatshouldEnumerator.Currentreturn? internalconstintDictEntry=1; internalconstintKeyValuePair=2; internalEnumerator(Dictionary<TKey,TValue>dictionary,intgetEnumeratorRetType){ this.dictionary=dictionary; version=dictionary.version; index=0; this.getEnumeratorRetType=getEnumeratorRetType; current=newKeyValuePair<TKey,TValue>(); } publicboolMoveNext(){ if(version!=dictionary.version){ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); } //Useunsignedcomparisonsincewesetindextodictionary.count+1whentheenumerationends. //dictionary.count+1couldbenegativeifdictionary.countisInt32.MaxValue while((uint)index<(uint)dictionary.count){ if(dictionary.entries[index].hashCode>=0){ current=newKeyValuePair<TKey,TValue>(dictionary.entries[index].key,dictionary.entries[index].value); index++; returntrue; } index++; } index=dictionary.count+1; current=newKeyValuePair<TKey,TValue>(); returnfalse; } publicKeyValuePair<TKey,TValue>Current{ get{returncurrent;} } publicvoidDispose(){ } objectIEnumerator.Current{ get{ if(index==0||(index==dictionary.count+1)){ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); } if(getEnumeratorRetType==DictEntry){ returnnewSystem.Collections.DictionaryEntry(current.Key,current.Value); }else{ returnnewKeyValuePair<TKey,TValue>(current.Key,current.Value); } } } voidIEnumerator.Reset(){ if(version!=dictionary.version){ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); } index=0; current=newKeyValuePair<TKey,TValue>(); } DictionaryEntryIDictionaryEnumerator.Entry{ get{ if(index==0||(index==dictionary.count+1)){ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); } returnnewDictionaryEntry(current.Key,current.Value); } } objectIDictionaryEnumerator.Key{ get{ if(index==0||(index==dictionary.count+1)){ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); } returncurrent.Key; } } objectIDictionaryEnumerator.Value{ get{ if(index==0||(index==dictionary.count+1)){ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); } returncurrent.Value; } } }
上面主要是对字典(Dictionary)的一些常用方法进行一个简单的说明。接下来主要阐述如何创建安全的字典(Dictionary)存储结构。有关线程安全的部分,在这里就不再赘述了。
///<summary> ///线程安全通用字典 ///</summary> ///<typeparamname="TKey"></typeparam> ///<typeparamname="TValue"></typeparam> publicclassTDictionary<TKey,TValue>:IDictionary<TKey,TValue> { ///<summary> ///锁定字典 ///</summary> privatereadonlyReaderWriterLockSlim_lockDictionary=newReaderWriterLockSlim(); ///<summary> ///基本字典 ///</summary> privatereadonlyDictionary<TKey,TValue>_mDictionary; //Variables ///<summary> ///初始化字典对象 ///</summary> publicTDictionary() { _mDictionary=newDictionary<TKey,TValue>(); } ///<summary> ///初始化字典对象 ///</summary> ///<paramname="capacity">字典的初始容量</param> publicTDictionary(intcapacity) { _mDictionary=newDictionary<TKey,TValue>(capacity); } ///<summary> ///初始化字典对象 ///</summary> ///<paramname="comparer">比较器在比较键时使用</param> publicTDictionary(IEqualityComparer<TKey>comparer) { _mDictionary=newDictionary<TKey,TValue>(comparer); } ///<summary> ///初始化字典对象 ///</summary> ///<paramname="dictionary">其键和值被复制到此对象的字典</param> publicTDictionary(IDictionary<TKey,TValue>dictionary) { _mDictionary=newDictionary<TKey,TValue>(dictionary); } ///<summary> ///初始化字典对象 ///</summary> ///<paramname="capacity">字典的初始容量</param> ///<paramname="comparer">比较器在比较键时使用</param> publicTDictionary(intcapacity,IEqualityComparer<TKey>comparer) { _mDictionary=newDictionary<TKey,TValue>(capacity,comparer); } ///<summary> ///初始化字典对象 ///</summary> ///<paramname="dictionary">其键和值被复制到此对象的字典</param> ///<paramname="comparer">比较器在比较键时使用</param> publicTDictionary(IDictionary<TKey,TValue>dictionary,IEqualityComparer<TKey>comparer) { _mDictionary=newDictionary<TKey,TValue>(dictionary,comparer); } publicTValueGetValueAddIfNotExist(TKeykey,Func<TValue>func) { return_lockDictionary.PerformUsingUpgradeableReadLock(()=> { TValuerVal; //如果我们有值,得到它并退出 if(_mDictionary.TryGetValue(key,outrVal)) returnrVal; //没有找到,所以做函数得到的值 _lockDictionary.PerformUsingWriteLock(()=> { rVal=func.Invoke(); //添加到字典 _mDictionary.Add(key,rVal); returnrVal; }); returnrVal; }); } ///<summary> ///将项目添加到字典 ///</summary> ///<paramname="key">添加的关键</param> ///<paramname="value">要添加的值</param> publicvoidAdd(TKeykey,TValuevalue) { _lockDictionary.PerformUsingWriteLock(()=>_mDictionary.Add(key,value)); } ///<summary> ///将项目添加到字典 ///</summary> ///<paramname="item">要添加的键/值</param> publicvoidAdd(KeyValuePair<TKey,TValue>item) { varkey=item.Key; varvalue=item.Value; _lockDictionary.PerformUsingWriteLock(()=>_mDictionary.Add(key,value)); } ///<summary> ///如果值不存在,则添加该值。返回如果值已添加,则为true ///</summary> ///<paramname="key">检查的关键,添加</param> ///<paramname="value">如果键不存在,则添加的值</param> publicboolAddIfNotExists(TKeykey,TValuevalue) { boolrVal=false; _lockDictionary.PerformUsingWriteLock(()=> { //如果不存在,则添加它 if(!_mDictionary.ContainsKey(key)) { //添加该值并设置标志 _mDictionary.Add(key,value); rVal=true; } }); returnrVal; } ///<summary> ///如果键不存在,则添加值列表。 ///</summary> ///<paramname="keys">要检查的键,添加</param> ///<paramname="defaultValue">如果键不存在,则添加的值</param> publicvoidAddIfNotExists(IEnumerable<TKey>keys,TValuedefaultValue) { _lockDictionary.PerformUsingWriteLock(()=> { foreach(TKeykeyinkeys) { //如果不存在,则添加它 if(!_mDictionary.ContainsKey(key)) _mDictionary.Add(key,defaultValue); } }); } publicboolAddIfNotExistsElseUpdate(TKeykey,TValuevalue) { varrVal=false; _lockDictionary.PerformUsingWriteLock(()=> { //如果不存在,则添加它 if(!_mDictionary.ContainsKey(key)) { //添加该值并设置标志 _mDictionary.Add(key,value); rVal=true; } else _mDictionary[key]=value; }); returnrVal; } ///<summary> ///如果键存在,则更新键的值。 ///</summary> ///<paramname="key"></param> ///<paramname="newValue"></param> publicboolUpdateValueIfKeyExists(TKeykey,TValuenewValue) { boolrVal=false; _lockDictionary.PerformUsingWriteLock(()=> { //如果我们有密钥,然后更新它 if(!_mDictionary.ContainsKey(key))return; _mDictionary[key]=newValue; rVal=true; }); returnrVal; } ///<summary> ///如果键值对存在于字典中,则返回true ///</summary> ///<paramname="item">键值对查找</param> publicboolContains(KeyValuePair<TKey,TValue>item) { return_lockDictionary.PerformUsingReadLock(()=>((_mDictionary.ContainsKey(item.Key))&& (_mDictionary.ContainsValue(item.Value)))); } publicboolContainsKey(TKeykey) { return_lockDictionary.PerformUsingReadLock(()=>_mDictionary.ContainsKey(key)); } ///<summary> ///如果字典包含此值,则返回true ///</summary> ///<paramname="value">找到的值</param> publicboolContainsValue(TValuevalue) { return_lockDictionary.PerformUsingReadLock(()=>_mDictionary.ContainsValue(value)); } publicICollection<TKey>Keys { get{return_lockDictionary.PerformUsingReadLock(()=>_mDictionary.Keys);} } publicboolRemove(TKeykey) { return_lockDictionary.PerformUsingWriteLock(()=>(!_mDictionary.ContainsKey(key))||_mDictionary.Remove(key)); } publicboolRemove(KeyValuePair<TKey,TValue>item) { return_lockDictionary.PerformUsingWriteLock(()=> { //如果键不存在则跳过 TValuetempVal; if(!_mDictionary.TryGetValue(item.Key,outtempVal)) returnfalse; //如果值不匹配,请跳过 returntempVal.Equals(item.Value)&&_mDictionary.Remove(item.Key); }); } ///<summary> ///从字典中删除与模式匹配的项 ///</summary> ///<paramname="predKey">基于键的可选表达式</param> ///<paramname="predValue">基于值的选项表达式</param> publicboolRemove(Predicate<TKey>predKey,Predicate<TValue>predValue) { return_lockDictionary.PerformUsingWriteLock(()=> { //如果没有键退出 if(_mDictionary.Keys.Count==0) returntrue; //保存要删除的项目列表 vardeleteList=newList<TKey>(); //过程密钥 foreach(varkeyin_mDictionary.Keys) { varisMatch=false; if(predKey!=null) isMatch=(predKey(key)); //如果此项目的值匹配,请添加它 if((!isMatch)&&(predValue!=null)&&(predValue(_mDictionary[key]))) isMatch=true; //如果我们有匹配,添加到列表 if(isMatch) deleteList.Add(key); } //从列表中删除所有项目 foreach(varitemindeleteList) _mDictionary.Remove(item); returntrue; }); } publicboolTryGetValue(TKeykey,outTValuevalue) { _lockDictionary.EnterReadLock(); try { return_mDictionary.TryGetValue(key,outvalue); } finally { _lockDictionary.ExitReadLock(); } } publicICollection<TValue>Values { get{return_lockDictionary.PerformUsingReadLock(()=>_mDictionary.Values);} } publicTValuethis[TKeykey] { get{return_lockDictionary.PerformUsingReadLock(()=>_mDictionary[key]);} set{_lockDictionary.PerformUsingWriteLock(()=>_mDictionary[key]=value);} } ///<summary> ///清除字典 ///</summary> publicvoidClear() { _lockDictionary.PerformUsingWriteLock(()=>_mDictionary.Clear()); } publicvoidCopyTo(KeyValuePair<TKey,TValue>[]array,intarrayIndex) { _lockDictionary.PerformUsingReadLock(()=>_mDictionary.ToArray().CopyTo(array,arrayIndex)); } ///<summary> ///返回字典中的项目数 ///</summary> publicintCount { get{return_lockDictionary.PerformUsingReadLock(()=>_mDictionary.Count);} } publicboolIsReadOnly { get{returnfalse;} } publicIEnumerator<KeyValuePair<TKey,TValue>>GetEnumerator() { Dictionary<TKey,TValue>localDict=null; _lockDictionary.PerformUsingReadLock(()=>localDict=newDictionary<TKey,TValue>(_mDictionary)); return((IEnumerable<KeyValuePair<TKey,TValue>>)localDict).GetEnumerator(); } System.Collections.IEnumeratorSystem.Collections.IEnumerable.GetEnumerator() { Dictionary<TKey,TValue>localDict=null; _lockDictionary.PerformUsingReadLock(()=>localDict=newDictionary<TKey,TValue>(_mDictionary)); returnlocalDict.GetEnumerator(); } }
以上创建安全的字典方法中,主要对字典的一些方法和属性进行重写操作,对某些方法进行锁设置。
以上就是本文的全部内容,希望对大家有所帮助,同时也希望多多支持毛票票!