C#创建安全的字典(Dictionary)存储结构

作者:彭泽0902 时间:2023-03-17 22:11:51 

在上面介绍过栈(Stack)的存储结构,接下来介绍另一种存储结构字典(Dictionary)。 字典(Dictionary)里面的每一个元素都是一个键值对(由二个元素组成:键和值) 键必须是唯一的,而值不需要唯一的,键和值都可以是任何类型。字典(Dictionary)是常用于查找和排序的列表。

  接下来看一下Dictionary的部分方法和类的底层实现代码:

  1.Add:将指定的键和值添加到字典中。


 public void Add(TKey key, TValue value) {
     Insert(key, value, true);
   }
private void Insert(TKey key, TValue value, bool add) {
      if( key == null ) {
       ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
     }
     if (buckets == null) Initialize(0);
     int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
     int targetBucket = hashCode % buckets.Length;
#if FEATURE_RANDOMIZED_STRING_HASHING
     int collisionCount = 0;
#endif
     for (int i = 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;
       }
#if FEATURE_RANDOMIZED_STRING_HASHING
       collisionCount++;
#endif
     }
     int index;
     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++;
#if FEATURE_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> 中移除所有的键和值。


public void Clear() {
     if (count > 0) {
       for (int i = 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> 中移除所指定的键的值。


public bool Remove(TKey key) {
     if(key == null) {
       ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
     }
     if (buckets != null) {
       int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
       int bucket = hashCode % buckets.Length;
       int last = -1;
       for (int i = 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++;
           return true;
         }
       }
     }
     return false;
   }

  4.GetEnumerator():返回循环访问 Dictionary<TKey, TValue> 的枚举器。


 public Enumerator GetEnumerator() {
     return new Enumerator(this, Enumerator.KeyValuePair);
   }
[Serializable]
   public struct Enumerator: IEnumerator<KeyValuePair<TKey,TValue>>,
     IDictionaryEnumerator
   {
     private Dictionary<TKey,TValue> dictionary;
     private int version;
     private int index;
     private KeyValuePair<TKey,TValue> current;
     private int getEnumeratorRetType; // What should Enumerator.Current return?
     internal const int DictEntry = 1;
     internal const int KeyValuePair = 2;
     internal Enumerator(Dictionary<TKey,TValue> dictionary, int getEnumeratorRetType) {
       this.dictionary = dictionary;
       version = dictionary.version;
       index = 0;
       this.getEnumeratorRetType = getEnumeratorRetType;
       current = new KeyValuePair<TKey, TValue>();
     }
     public bool MoveNext() {
       if (version != dictionary.version) {
         ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
       }
       // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
       // dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
       while ((uint)index < (uint)dictionary.count) {
         if (dictionary.entries[index].hashCode >= 0) {
           current = new KeyValuePair<TKey, TValue>(dictionary.entries[index].key, dictionary.entries[index].value);
           index++;
           return true;
         }
         index++;
       }
       index = dictionary.count + 1;
       current = new KeyValuePair<TKey, TValue>();
       return false;
     }
     public KeyValuePair<TKey,TValue> Current {
       get { return current; }
     }
     public void Dispose() {
     }
     object IEnumerator.Current {
       get {
         if( index == 0 || (index == dictionary.count + 1)) {
           ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
         }
         if (getEnumeratorRetType == DictEntry) {
           return new System.Collections.DictionaryEntry(current.Key, current.Value);
         } else {
           return new KeyValuePair<TKey, TValue>(current.Key, current.Value);
         }
       }
     }
     void IEnumerator.Reset() {
       if (version != dictionary.version) {
         ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
       }
       index = 0;
       current = new KeyValuePair<TKey, TValue>();
     }
     DictionaryEntry IDictionaryEnumerator.Entry {
       get {
         if( index == 0 || (index == dictionary.count + 1)) {
            ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
         }
         return new DictionaryEntry(current.Key, current.Value);
       }
     }
     object IDictionaryEnumerator.Key {
       get {
         if( index == 0 || (index == dictionary.count + 1)) {
            ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
         }
         return current.Key;
       }
     }
     object IDictionaryEnumerator.Value {
       get {
         if( index == 0 || (index == dictionary.count + 1)) {
            ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
         }
         return current.Value;
       }
     }
   }

     上面主要是对字典(Dictionary)的一些常用方法进行一个简单的说明。接下来主要阐述如何创建安全的字典(Dictionary)存储结构。有关线程安全的部分,在这里就不再赘述了。


 /// <summary>
 /// 线程安全通用字典
 /// </summary>
 /// <typeparam name="TKey"></typeparam>
 /// <typeparam name="TValue"></typeparam>
 public class TDictionary<TKey, TValue> : IDictionary<TKey, TValue>
 {
   /// <summary>
   /// 锁定字典
   /// </summary>
   private readonly ReaderWriterLockSlim _lockDictionary = new ReaderWriterLockSlim();
   /// <summary>
   ///基本字典
   /// </summary>
   private readonly Dictionary<TKey, TValue> _mDictionary;
   // Variables
   /// <summary>
   /// 初始化字典对象
   /// </summary>
   public TDictionary()
   {
     _mDictionary = new Dictionary<TKey, TValue>();
   }
   /// <summary>
   /// 初始化字典对象
   /// </summary>
   /// <param name="capacity">字典的初始容量</param>
   public TDictionary(int capacity)
   {
     _mDictionary = new Dictionary<TKey, TValue>(capacity);
   }
   /// <summary>
   ///初始化字典对象
   /// </summary>
   /// <param name="comparer">比较器在比较键时使用</param>
   public TDictionary(IEqualityComparer<TKey> comparer)
   {
     _mDictionary = new Dictionary<TKey, TValue>(comparer);
   }
   /// <summary>
   /// 初始化字典对象
   /// </summary>
   /// <param name="dictionary">其键和值被复制到此对象的字典</param>
   public TDictionary(IDictionary<TKey, TValue> dictionary)
   {
     _mDictionary = new Dictionary<TKey, TValue>(dictionary);
   }
   /// <summary>
   ///初始化字典对象
   /// </summary>
   /// <param name="capacity">字典的初始容量</param>
   /// <param name="comparer">比较器在比较键时使用</param>
   public TDictionary(int capacity, IEqualityComparer<TKey> comparer)
   {
     _mDictionary = new Dictionary<TKey, TValue>(capacity, comparer);
   }
   /// <summary>
   /// 初始化字典对象
   /// </summary>
   /// <param name="dictionary">其键和值被复制到此对象的字典</param>
   /// <param name="comparer">比较器在比较键时使用</param>
   public TDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
   {
     _mDictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
   }
   public TValue GetValueAddIfNotExist(TKey key, Func<TValue> func)
   {
     return _lockDictionary.PerformUsingUpgradeableReadLock(() =>
     {
       TValue rVal;

// 如果我们有值,得到它并退出
       if (_mDictionary.TryGetValue(key, out rVal))
         return rVal;
       // 没有找到,所以做函数得到的值
       _lockDictionary.PerformUsingWriteLock(() =>
       {
         rVal = func.Invoke();
         // 添加到字典
         _mDictionary.Add(key, rVal);
         return rVal;
       });
       return rVal;
     });
   }
   /// <summary>
   /// 将项目添加到字典
   /// </summary>
   /// <param name="key">添加的关键</param>
   /// <param name="value">要添加的值</param>
   public void Add(TKey key, TValue value)
   {
     _lockDictionary.PerformUsingWriteLock(() => _mDictionary.Add(key, value));
   }
   /// <summary>
   ///将项目添加到字典
   /// </summary>
   /// <param name="item">要添加的键/值</param>
   public void Add(KeyValuePair<TKey, TValue> item)
   {
     var key = item.Key;
     var value = item.Value;
     _lockDictionary.PerformUsingWriteLock(() => _mDictionary.Add(key, value));
   }
   /// <summary>
   /// 如果值不存在,则添加该值。 返回如果值已添加,则为true
   /// </summary>
   /// <param name="key">检查的关键,添加</param>
   /// <param name="value">如果键不存在,则添加的值</param>
   public bool AddIfNotExists(TKey key, TValue value)
   {
     bool rVal = false;
     _lockDictionary.PerformUsingWriteLock(() =>
     {
       // 如果不存在,则添加它
       if (!_mDictionary.ContainsKey(key))
       {
         // 添加该值并设置标志
         _mDictionary.Add(key, value);
         rVal = true;
       }
     });
     return rVal;
   }
   /// <summary>
   /// 如果键不存在,则添加值列表。
   /// </summary>
   /// <param name="keys">要检查的键,添加</param>
   /// <param name="defaultValue">如果键不存在,则添加的值</param>
   public void AddIfNotExists(IEnumerable<TKey> keys, TValue defaultValue)
   {
     _lockDictionary.PerformUsingWriteLock(() =>
     {
       foreach (TKey key in keys)
       {
         // 如果不存在,则添加它
         if (!_mDictionary.ContainsKey(key))
           _mDictionary.Add(key, defaultValue);
       }
     });
   }
   public bool AddIfNotExistsElseUpdate(TKey key, TValue value)
   {
     var rVal = false;
     _lockDictionary.PerformUsingWriteLock(() =>
     {
       // 如果不存在,则添加它
       if (!_mDictionary.ContainsKey(key))
       {
         // 添加该值并设置标志
         _mDictionary.Add(key, value);
         rVal = true;
       }
       else
         _mDictionary[key] = value;
     });
     return rVal;
   }
   /// <summary>
   /// 如果键存在,则更新键的值。
   /// </summary>
   /// <param name="key"></param>
   /// <param name="newValue"></param>
   public bool UpdateValueIfKeyExists(TKey key, TValue newValue)
   {
     bool rVal = false;
     _lockDictionary.PerformUsingWriteLock(() =>
     {
       // 如果我们有密钥,然后更新它
       if (!_mDictionary.ContainsKey(key)) return;
       _mDictionary[key] = newValue;
       rVal = true;
     });
     return rVal;
   }
   /// <summary>
   /// 如果键值对存在于字典中,则返回true
   /// </summary>
   /// <param name="item">键值对查找</param>
   public bool Contains(KeyValuePair<TKey, TValue> item)
   {
     return _lockDictionary.PerformUsingReadLock(() => ((_mDictionary.ContainsKey(item.Key)) &&
                              (_mDictionary.ContainsValue(item.Value))));
   }
   public bool ContainsKey(TKey key)
   {
     return _lockDictionary.PerformUsingReadLock(() => _mDictionary.ContainsKey(key));
   }
   /// <summary>
   /// 如果字典包含此值,则返回true
   /// </summary>
   /// <param name="value">找到的值</param>
   public bool ContainsValue(TValue value)
   {
     return _lockDictionary.PerformUsingReadLock(() => _mDictionary.ContainsValue(value));
   }
   public ICollection<TKey> Keys
   {
     get { return _lockDictionary.PerformUsingReadLock(() => _mDictionary.Keys); }
   }
   public bool Remove(TKey key)
   {
     return _lockDictionary.PerformUsingWriteLock(() => (!_mDictionary.ContainsKey(key)) || _mDictionary.Remove(key));
   }
   public bool Remove(KeyValuePair<TKey, TValue> item)
   {
     return _lockDictionary.PerformUsingWriteLock(() =>
     {
       // 如果键不存在则跳过
       TValue tempVal;
       if (!_mDictionary.TryGetValue(item.Key, out tempVal))
         return false;
       //如果值不匹配,请跳过
       return tempVal.Equals(item.Value) && _mDictionary.Remove(item.Key);
     });
   }
   /// <summary>
   /// 从字典中删除与模式匹配的项
   /// </summary>
   /// <param name="predKey">基于键的可选表达式</param>
   /// <param name="predValue">基于值的选项表达式</param>
   public bool Remove(Predicate<TKey> predKey, Predicate<TValue> predValue)
   {
     return _lockDictionary.PerformUsingWriteLock(() =>
     {
       // 如果没有键退出
       if (_mDictionary.Keys.Count == 0)
         return true;
       //保存要删除的项目列表
       var deleteList = new List<TKey>();
       // 过程密钥
       foreach (var key in _mDictionary.Keys)
       {
         var isMatch = false;
         if (predKey != null)
           isMatch = (predKey(key));
         // 如果此项目的值匹配,请添加它
         if ((!isMatch) && (predValue != null) && (predValue(_mDictionary[key])))
           isMatch = true;
         // 如果我们有匹配,添加到列表
         if (isMatch)
           deleteList.Add(key);
       }
       // 从列表中删除所有项目
       foreach (var item in deleteList)
         _mDictionary.Remove(item);
       return true;
     });
   }
   public bool TryGetValue(TKey key, out TValue value)
   {
     _lockDictionary.EnterReadLock();
     try
     {
       return _mDictionary.TryGetValue(key, out value);
     }
     finally
     {
       _lockDictionary.ExitReadLock();
     }
   }
   public ICollection<TValue> Values
   {
     get { return _lockDictionary.PerformUsingReadLock(() => _mDictionary.Values); }
   }
   public TValue this[TKey key]
   {
     get { return _lockDictionary.PerformUsingReadLock(() => _mDictionary[key]); }
     set { _lockDictionary.PerformUsingWriteLock(() => _mDictionary[key] = value); }
   }
   /// <summary>
   /// 清除字典
   /// </summary>
   public void Clear()
   {
     _lockDictionary.PerformUsingWriteLock(() => _mDictionary.Clear());
   }
   public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
   {
     _lockDictionary.PerformUsingReadLock(() => _mDictionary.ToArray().CopyTo(array, arrayIndex));
   }
   /// <summary>
   /// 返回字典中的项目数
   /// </summary>
   public int Count
   {
     get { return _lockDictionary.PerformUsingReadLock(() => _mDictionary.Count); }
   }
   public bool IsReadOnly
   {
     get { return false; }
   }
   public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
   {
     Dictionary<TKey, TValue> localDict = null;
     _lockDictionary.PerformUsingReadLock(() => localDict = new Dictionary<TKey, TValue>(_mDictionary));
     return ((IEnumerable<KeyValuePair<TKey, TValue>>)localDict).GetEnumerator();
   }
   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
   {
     Dictionary<TKey, TValue> localDict = null;
     _lockDictionary.PerformUsingReadLock(() => localDict = new Dictionary<TKey, TValue>(_mDictionary));
     return localDict.GetEnumerator();
   }
 }

    以上创建安全的字典方法中,主要对字典的一些方法和属性进行重写操作,对某些方法进行锁设置。

来源:http://www.cnblogs.com/pengze0902/p/5993615.html

标签:C#,字典,存储结构
0
投稿

猜你喜欢

  • SpringBoot中定位切点的两种常用方法

    2023-09-26 08:45:17
  • Spring Boot 配置和使用多线程池的实现

    2022-09-04 19:53:02
  • android实现蓝牙文件发送的实例代码,支持多种机型

    2023-08-17 11:07:56
  • Spring MVC深入学习之启动初始化过程

    2023-07-16 07:04:21
  • SpringBoot使用validation-api实现对枚举类参数校验的方法

    2021-09-22 19:21:32
  • .Net Winform开发笔记(四)透过现象看本质

    2022-06-22 09:36:24
  • Mybatis初始化知识小结

    2023-11-01 13:59:27
  • 细说C#中的枚举:转换、标志和属性

    2021-07-10 06:01:05
  • 浅谈android Fragment横竖屏翻转对重新加载的要求

    2023-07-27 21:55:28
  • IDEA 2020.2 +Gradle 6.6.1 + Spring Boot 2.3.4 创建多模块项目的超详细教程

    2021-11-08 00:42:36
  • SpringBoot加载外部依赖过程解析

    2021-11-23 22:30:00
  • Java基于享元模式实现五子棋游戏功能实例详解

    2023-07-23 16:20:18
  • Android拍照或从图库选择图片并裁剪

    2023-07-01 08:21:45
  • 解析springboot整合谷歌开源缓存框架Guava Cache原理

    2023-11-07 13:24:23
  • 序列化版本号serialVersionUID的作用_动力节点Java学院整理

    2022-08-14 06:39:02
  • 详解Java字节码编程之非常好用的javassist

    2021-08-27 04:54:30
  • Java split函数拆分后变成null问题解决方案

    2022-05-24 17:00:36
  • Android仿IOS自定义AlertDialog提示框

    2022-08-23 21:08:44
  • Java全面细致讲解类与对象

    2022-07-07 07:04:42
  • java实现变更文件查询的方法

    2022-07-29 04:55:37
  • asp之家 软件编程 m.aspxhome.com