zoukankan      html  css  js  c++  java
  • 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();
            }
    
        }

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

  • 相关阅读:
    C语言调用汇编函数 实现超过32位数的加法
    【Qt学习笔记】13_富文本及打印页面
    Java初级回顾
    Java中FileInputStream和FileOutputStream类实现文件夹及文件的复制粘贴
    Java中File类如何扫描磁盘所有文件包括子目录及子目录文件
    学习笔记之循环链表
    练习 hdu 5523 Game
    学习笔记之集合ArrayList(1)和迭代器
    学习笔记之工厂方法模式
    学习笔记之基本数据类型-包装类-String之间的转换
  • 原文地址:https://www.cnblogs.com/pengze0902/p/5993615.html
Copyright © 2011-2022 走看看