考虑到字典键查找和删除的性能,因为它们是哈希操作,并且考虑到问题的措辞是最好的方式,我认为下面是一个完全有效的方法,而其他方法有点过于复杂,恕我冒昧。
public static void MergeOverwrite<T1, T2>(this IDictionary<T1, T2> dictionary, IDictionary<T1, T2> newElements)
{
if (newElements == null) return;
foreach (var e in newElements)
{
dictionary.Remove(e.Key); //or if you don't want to overwrite do (if !.Contains()
dictionary.Add(e);
}
}
或者如果你在多线程应用程序中工作,你的字典无论如何都需要线程安全,你应该这样做:
public static void MergeOverwrite<T1, T2>(this ConcurrentDictionary<T1, T2> dictionary, IDictionary<T1, T2> newElements)
{
if (newElements == null || newElements.Count == 0) return;
foreach (var ne in newElements)
{
dictionary.AddOrUpdate(ne.Key, ne.Value, (key, value) => value);
}
}
然后可以对其进行包装,使其处理字典的枚举。无论如何,您看到的是~O(3n)(所有条件都是完美的),因为. add()将在幕后执行额外的、不必要的但实际上是免费的Contains()。我觉得没有比这更好的了。
如果希望限制大型集合上的额外操作,则应该将将要合并的每个字典的Count相加,并将目标字典的容量设置为该值,这样可以避免以后调整大小的成本。最终产品是这样的…
public static IDictionary<T1, T2> MergeAllOverwrite<T1, T2>(IList<IDictionary<T1, T2>> allDictionaries)
{
var initSize = allDictionaries.Sum(d => d.Count);
var resultDictionary = new Dictionary<T1, T2>(initSize);
allDictionaries.ForEach(resultDictionary.MergeOverwrite);
return resultDictionary;
}
注意,我在这个方法中引入了一个IList<T>…主要是因为如果你接受一个IEnumerable<T>,你已经向同一个集合的多个枚举开放了,如果你从一个延迟的LINQ语句中获得字典集合,这可能是非常昂贵的。