您的位置:首页 > 编程语言 > C#

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

2016-10-24 16:54 260 查看
在上面介绍过栈(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);
}

/// <summary>
/// 返回的值<paramref name="key"/>. 如果 <paramref name="key"/>不存在<paramref name="func"/>被执行并添加到字典
/// </summary>
/// <param name="key">检查的关键</param>
/// <param name="func">如果键不存在,委托调用</param>
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);
}
});
}

// 添加如果不存在
/// <summary>
/// 如果值不存在,则添加该值。返回值如果值已添加,则返回true。如果键已经存在,则其值将更新并返回false。
/// </summary>
/// <param name="key">检查的关键,添加</param>
/// <param name="value">如果键不存在,则添加的值</param>
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>
/// 如果键存在,则更新键的值。 如果更新,则返回true
/// </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))));
}

/// <summary>
/// 如果键存在于字典中,则返回true
/// </summary>
/// <param name="key">在字典中找到的关键</param>
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));
}

/// <summary>
/// 将键作为集合返回
/// </summary>
public ICollection<TKey> Keys
{
get { return _lockDictionary.PerformUsingReadLock(() => _mDictionary.Keys); }
}

/// <summary>
/// 删除具有此键名称的元素
/// </summary>
/// <param name="key">删除的关键</param>
public bool Remove(TKey key)
{
return _lockDictionary.PerformUsingWriteLock(() => (!_mDictionary.ContainsKey(key)) || _mDictionary.Remove(key));
}

/// <summary>
/// 删除具有此键名称和值的元素。 返回如果项目已删除,则为true。
/// </summary>
/// <param name="item">删除的键</param>
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>
/// 从字典中删除与模式匹配的项。返回true成功
/// </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;
});
}

/// <summary>
/// 尝试返回在元素中找到的值 <paramref name="key"/> 如果未找到任何值,则返回false
/// </summary>
/// <param name="key">找到的关键</param>
/// <param name="value">如果找到该键,则返回值</param>
public bool TryGetValue(TKey key, out TValue value)
{
_lockDictionary.EnterReadLock();
try
{
return _mDictionary.TryGetValue(key, out value);
}
finally
{
_lockDictionary.ExitReadLock();
}

}

// 尝试获取值
/// <summary>
///返回字典中值的集合
/// </summary>
public ICollection<TValue> Values
{
get { return _lockDictionary.PerformUsingReadLock(() => _mDictionary.Values); }
}

/// <summary>
/// 值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
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());
}

/// <summary>
/// 将字典的项目复制到键值对数组
/// </summary>
/// <param name="array">将键值对集合复制到</param>
/// <param name="arrayIndex">开始复制的索引</param>
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); }
}

/// <summary>
///始终返回false
/// </summary>
public bool IsReadOnly
{
get { return false; }
}

/// <summary>
/// 枚举器
/// </summary>
/// <returns></returns>
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();
}

/// <summary>
///获取枚举器
/// </summary>
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
Dictionary<TKey, TValue> localDict = null;

_lockDictionary.PerformUsingReadLock(() => localDict = new Dictionary<TKey, TValue>(_mDictionary));

return localDict.GetEnumerator();
}

}
以上创建安全的字典方法中,主要对字典的一些方法和属性进行重写操作,对某些方法进行锁设置。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  NET Dictionary 线程