在字典中添加新项目或更新现有项目的方法
Posted
技术标签:
【中文标题】在字典中添加新项目或更新现有项目的方法【英文标题】:Method to Add new or update existing item in Dictionary 【发布时间】:2011-05-13 19:17:14 【问题描述】:在一些遗留代码中,我看到了以下扩展方法,以方便添加新的键值项或更新值(如果键已存在)。
方法 1(旧代码)。
public static void CreateNewOrUpdateExisting<TKey, TValue>(
this IDictionary<TKey, TValue> map, TKey key, TValue value)
if (map.ContainsKey(key))
map[key] = value;
else
map.Add(key, value);
不过,我已经检查过map[key]=value
的工作完全相同。即该方法可以替换为下面的方法二。
方法二。
public static void CreateNewOrUpdateExisting<TKey, TValue>(
this IDictionary<TKey, TValue> map, TKey key, TValue value)
map[key] = value;
现在,我的问题是.. 如果我用 Method-2 替换 Method-1 会有什么问题吗?它会在任何可能的情况下中断吗?
另外,我认为这曾经是 HashTable 和 Dictionary 之间的区别。 HashTable 允许更新项目,或使用索引器添加新项目,而 Dictionary 不允许!在 C# > 3.0 版本中是否消除了这种差异?
这个方法的目的是如果用户再次发送相同的key-value不会抛出异常,该方法应该只是用新的值更新条目,如果已经发送了新的key-value对则创建一个新的条目方法。
【问题讨论】:
【参考方案1】:如果我将 Method-1 替换为 Method-2 会有什么问题吗?
不,只需使用map[key] = value
。这两个选项是等价的。
关于Dictionary<>
与Hashtable
:当你启动Reflector 时,你会看到两个类的索引器设置器都调用this.Insert(key, value, add: false);
并且add
参数负责在插入重复键时引发异常。所以这两个类的行为是相同的。
【讨论】:
【参考方案2】:没有问题。我什至会从源代码中删除CreateNewOrUpdateExisting
并直接在您的代码中使用map[key] = value
,因为这是惯用的C#; C# 开发人员通常会知道map[key] = value
表示添加或更新。
【讨论】:
【参考方案3】:老问题,但我觉得我应该添加以下内容,甚至更多,因为在编写问题时.net 4.0 已经启动。
从 .net 4.0 开始,命名空间 System.Collections.Concurrent
包含线程安全的集合。
集合System.Collections.Concurrent.ConcurrentDictionary<>
完全符合您的要求。它具有AddOrUpdate()
方法以及线程安全的附加优势。
如果您处于高性能场景并且不处理多个线程,那么map[key] = value
已经给出的答案会更快。
在大多数情况下,这种性能优势是微不足道的。如果是这样,我建议使用 ConcurrentDictionary,因为:
-
它在框架中 - 经过更多测试,您不是必须维护代码的人
它是可扩展的:如果你切换到多线程,你的代码已经准备好了
【讨论】:
【参考方案4】:在功能上,它们是等价的。
性能方面map[key] = value
会更快,因为您只进行一次查找而不是两次。
风格方面,越短越好:)
在大多数情况下,代码似乎在多线程上下文中运行良好。但是,如果没有额外的同步,它是不是线程安全的。
【讨论】:
【参考方案5】:唯一的问题可能是如果有一天
地图[键] = 值
将转变为 -
地图[键]++;
这将导致 KeyNotFoundException。
【讨论】:
【参考方案6】:我知道它不是 Dictionary<TKey, TValue>
类,但是你可以避免 KeyNotFoundException
同时增加如下值:
dictionary[key]++; // throws `KeyNotFoundException` if there is no such key
通过使用ConcurrentDictionary<TKey, TValue> and its really nice method AddOrUpdate().。
让我举个例子:
var str = "Hellooo!!!";
var characters = new ConcurrentDictionary<char, int>();
foreach (var ch in str)
characters.AddOrUpdate(ch, 1, (k, v) => v + 1);
【讨论】:
是的,看起来很不错...但是ConcurrentDictionary
为多线程(即锁)增加了很多同步开销。因此会对性能产生重大影响。以上是关于在字典中添加新项目或更新现有项目的方法的主要内容,如果未能解决你的问题,请参考以下文章