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

在上面介绍过栈(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();
    }
  }

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

以上就是本文的全部内容,希望对大家有所帮助,同时也希望多多支持我们!

(0)

相关推荐

  • C#后台接受前台JSON字符串装换成字典集合处理

    一直以来,我们都是在服务端查询出结果生成JSON字符串,供前端调用,那么我们能否把从前端接受的JSON字符串转换成字典集合,让后台处理呢? 比如从前端接收:{'size':'10', 'weight':'10kg'} 在服务端转换成:[{size:"10"},{weight:"10kg"}]这样的字典集合 通过Newtonsoft的DeserializeObject<Dictionary<string, string>>方法可以把JSON字符

  • C#创建安全的栈(Stack)存储结构

    在C#中,用于存储的结构较多,如:DataTable,DataSet,List,Dictionary,Stack等结构,各种结构采用的存储的方式存在差异,效率也必然各有优缺点.现在介绍一种后进先出的数据结构. 谈到存储结构,我们在项目中使用的较多.对于Task存储结构,栈与队列是类似的结构,在使用的时候采用不同的方法.C#中栈(Stack)是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义:堆是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小.

  • 在C#使用字典存储事件示例及实现自定义事件访问器

    使用字典存储事件实例 accessor-declarations 的一种用法是公开很多事件但不为每个事件分配字段,而是使用字典来存储这些事件实例.这只在具有很多事件但您预计大多数事件都不会实现时才有用. public delegate void EventHandler1(int i); public delegate void EventHandler2(string s); public class PropertyEventsSample { private System.Collecti

  • C#简单的通用基础字典实现方法

    本文实例讲述了C#简单的通用基础字典实现方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Alif.Alif_WSAPI; using System.Data; using System.Windows.Forms; namespace Alif.AlifForm.CommClass {    

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

    在上面介绍过栈(Stack)的存储结构,接下来介绍另一种存储结构字典(Dictionary). 字典(Dictionary)里面的每一个元素都是一个键值对(由二个元素组成:键和值) 键必须是唯一的,而值不需要唯一的,键和值都可以是任何类型.字典(Dictionary)是常用于查找和排序的列表. 接下来看一下Dictionary的部分方法和类的底层实现代码: 1.Add:将指定的键和值添加到字典中. public void Add(TKey key, TValue value) { Insert(

  • Python3 字典dictionary入门基础附实例

    Python字典是另一种可变容器模型,且可存储任意类型对象,如字符串.数字.元组等其他容器模型.字典由键和对应值成对组成.字典也被称作关联数组或哈希表. 注意: 1.每个键与值用冒号隔开(:),每对用逗号,每对用逗号分割,整体放在花括号中({}). 2.键必须独一无二,但值则不必. 3.值可以取任何数据类型,但必须是不可变的,如字符串,数或元组. 字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在

  • Python 字典(Dictionary)详细介绍

    目录 1.访问字典里的值 2.修改字典 3.删除字典元素 3.1字典键的特性 4.字典内置函数&方法 字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值 key=>value 对用冒号 : 分割,每个键值对之间用逗号 , 分割,整个字典包括在花括号 {} 中 格式如下所示: d = {key1 : value1, key2 : value2 } 注意:dict 作为 Python 的关键字和内置函数,变量名不建议命名为 dict. 键一般是唯一的,如果重复最后的一个键值对会替换

  • 关于Python字典(Dictionary)操作详解

    目录 一.创建字典 二.访问字典里的值 三.修改字典 四.删除字典元素 五.字典键的特性 六.字典内置函数&方法 Python字典是另一种可变容器模型,且可存储任意类型对象,如字符串.数字.元组等其他容器模型. 一.创建字典 字典由键和对应值成对组成.字典也被称作关联数组或哈希表.基本语法如下: dict = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'} 也可如此创建字典 dict1 = { 'abc': 456 } dict2 = { '

  • Python 字典(Dictionary)操作详解

    Python字典是另一种可变容器模型,且可存储任意类型对象,如字符串.数字.元组等其他容器模型.一.创建字典字典由键和对应值成对组成.字典也被称作关联数组或哈希表.基本语法如下: 复制代码 代码如下: dict = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'} 也可如此创建字典: 复制代码 代码如下: dict1 = { 'abc': 456 };dict2 = { 'abc': 123, 98.6: 37 }; 注意:每个键与值用冒号隔开

  • python创建和使用字典实例详解

    字典是python中唯一内建的映射类型.字典中的值并没有特殊的顺序,但是都存储在一个特定的键(key)里.键可以是数字,字符串甚至是元组.1. 创建和使用字典字典可以通过下面的方式创建: 复制代码 代码如下: phonebook = {'Alice':'2341','Beth':'9102','Ceil':'3258'} 字典由多个键及与其对应的值构成的对组成.每个键和它的值之间用冒号(:)隔开,项之间用逗号(,)隔开,而整个字典是由一对大括号括起来.空字典:{} 1.1 dict函数可以用di

  • Java栈之链式栈存储结构的实现代码

    Java栈之链式栈存储结构实现 一.链栈 采用单链表来保存栈中所有元素,这种链式结构的栈称为链栈. 二.栈的链式存储结构实现 package com.ietree.basic.datastructure.stack; /** * 链栈 * * Created by ietree * 2017/4/29 */ public class LinkStack<T> { // 定义一个内部类Node,Node实例代表链栈的节点 private class Node { // 保存节点的数据 priva

  • JAVA 实现二叉树(链式存储结构)

    二叉树的分类(按存储结构) 树的分类(按存储结构) 顺序存储(用数组表示(静态二叉树))   链式存储 一些特别的二叉根: 完全二叉树,平衡二叉树(AVL),线索二叉树,三叉的(带父亲的指针)    二叉搜索树或者叫二叉 查找树(BST)  所用二叉树如下图所示: 二叉树的Java实现(链式存储结构) class TreeNode { private int key = 0; private String data = null; private boolean isVisted = false

  • java线性表的存储结构及其代码实现

    Java数据结构学习笔记第一篇: 用程序后在那个的数据大致有四种基本的逻辑结构: 集合:数据元素之间只有"同属于一个集合"的关系 线性结构:数据元素之间存在一个对一个的关系 树形结构:数据元素之间存在一个对多个关系 图形结构或网状结构:数据元素之间存在多个对多个的关系 对于数据不同的逻辑结构,计算机在物理磁盘上通常有两种屋里存储结构 顺序存储结构 链式存储结构 本篇博文主要讲的是线性结构,而线性结构主要是线性表,非线性结构主要是树和图. 线性表的基本特征: 总存在唯一的第一个数据元素

随机推荐