问题背景
最近遇到个问题,Dictionary字典存储的时候需要根据两个key,才能确定一个具体的value值。
ConcurrentDictionary和Dictionary
由于是在线程上进行操作,我用到的字典是ConcurrentDictionary,区别于普通的Dictionary。(这里也是一开始使用Dictionary,然后遇到跨线程问题,抛出异常,所以相比之下选择了ConcurrentDictionary)
在C#中,Dictionary是一个常见的字典类型,但它不是线程安全的。为了在多线程环境中确保安全的操作,我们可以使用ConcurrentDictionary,这是一个专门设计用于多线程场景的线程安全字典。
ConcurrentDictionary提供了内置的线程安全机制,避免了多线程同时访问时的问题。
所以,单线程建议用Dictionary,多线程建议用ConcurrentDictionary
1.两个key对应一个value
1)可以使用双重字典,即字典里面嵌套字典的方式实现
//Dictionary<key1, Dictionary<key2, value>> dict1 = new System.Collections.Generic.Dictionary<key1, Dictionary<key2, value>>();
Dictionary<string, Dictionary<string, string>> dict1 = new Dictionary<string, Dictionary<string, string>>();
Dictionary<string, Dictionary<string, string>> dict1 = new Dictionary<string, Dictionary<string, string>>();
/// <summary>
/// 赋值
/// </summary>
public void SetValue(string key1, string key2, string value)
{
if (dict1.ContainsKey(key1))
{
Dictionary<string,string> dict2 = dict1[key1];
if (dict2.ContainsKey(key2))
dict2[key2] = value;
else
dict2.Add(key2, value);
}
else
{
Dictionary<string,string> dict2 = new Dictionary<string, string>();
dict2.Add(key2, value);
dict1.Add(key1, dict2);
}
}
/// <summary>
/// 取值
/// </summary>
public string GetValue(string key1, string key2, string defaultValue="")
{
if (dict1.ContainsKey(key1))
{
Dictionary<string, string> dict2 = dict1[key1];
if (dict2.ContainsKey(key2))
return dict2[key2];
}
return defaultValue;
}
2)也可以使用Tuple 二元组
ConcurrentDictionary<Tuple<string, string>, string> pMultiDict = new ConcurrentDictionary<Tuple<string, string>, string>();
public void MutilDict(string pkey1,string pkey2,string pvalue)
{
//取值
string value = pMultiDict[new Tuple<string, string>(pkey1, pkey2)];
//添加
pMultiDict.TryAdd(new Tuple<string, string>(pkey1, pkey2), pvalue);
//删除
pMultiDict.TryRemove(new Tuple<string, string>(pkey1, pkey2), out string outValue);
//更新
pMultiDict.TryUpdate(new Tuple<string, string>(pkey1, pkey2), pvalue,value);
}
2.一个key对应多个value
/// <summary>
/// 复合字典 一键多值 用来存储 一个key对应多个value的情况
/// </summary>
/// <param name="mutilValueDict"></param>
/// <param name="pkey">key</param>
/// <param name="pvalue">value</param>
/// <param name="valueList"></param>
/// <param name="pMethod">add/removeKey/removeValue</param>
private void MultiValueDict(ConcurrentDictionary<string, List<string>> pMutilValueDict, List<string> pValueList, string pkey, string pvalue, string pMethod)
{
try
{
//赋值给临时字典,列表 进行操作
ConcurrentDictionary<string, List<string>> mutilValueDict = pMutilValueDict;
List<string> valueList = pValueList;
switch (pMethod)
{
case "add":
//add
if (mutilValueDict.ContainsKey(pkey))
{
List<string> tempList = mutilValueDict[pkey];
if (!tempList.Contains(pvalue))
{
tempList.Add(pvalue);
}
mutilValueDict.AddOrUpdate(pkey, tempList, (oldKey, oleValue) => tempList);
}
else
{
List<string> tempList = new List<string>();
tempList.Add(pvalue);
mutilValueDict.TryAdd(pkey, tempList);
}
if (!valueList.Contains(pvalue))
{
valueList.Add(pvalue);
}
break;
case "removeValue":
//remove
if (mutilValueDict.ContainsKey(pkey))
{
List<string> tempList = mutilValueDict[pkey];
if (tempList.Contains(pvalue))
{
tempList.Remove(pvalue);
}
mutilValueDict.AddOrUpdate(pkey, tempList, (mOldKey, mOldValue) => tempList);
}
if (valueList.Contains(pvalue))
{
valueList.Remove(pvalue);
}
break;
case "removeKey":
if (mutilValueDict.ContainsKey(pkey))
{
List<string> tempList = mutilValueDict[pkey];
foreach (string item in tempList)
{
valueList.Remove(item);
}
mutilValueDict.TryRemove(pkey, out List<string> list);
}
break;
}
//操作完成之后赋值
MutliValueDict = mutilValueDict;
MutliValueList = valueList;
}
catch (Exception e)
{
SaveLog("MultiValueDict操作失败" + e.Message + e.StackTrace);
}
}