情况1:
Dictionary<string,object> valuesDict;// valuesDict loaded with thousands of objectsforeach (object value in valuesDict.Values) { /* process */ }
案例2:
List<object> valuesList;// valuesList loaded with thousands of objectsforeach (object value in valuesList) { /* process */ }
更新:
背景:
字典对于其他地方的键控搜索是有益的(而不是遍历列表),但是如果遍历字典比通过列表慢得多,那么好处将会减少.
更新:
根据许多人的建议,我已经完成了自己的测试.
首先,这些是结果.以下是该计划.
迭代整个集合
Dict:78
凯德:131
清单:76
键控搜索集合
Dict:178
凯德:194
清单:142800
using System;using System.linq;namespace IterateCollections{ public class Data { public string ID; public string Text; } public class KeyedData : System.Collections.ObjectModel.KeyedCollection<string,Data> { protected overrIDe string GetKeyForItem(Data item) { return item.ID; } } class Program { static voID Main(string[] args) { var dict = new System.Collections.Generic.Dictionary<string,Data>(); var List = new System.Collections.Generic.List<Data>(); var keyd = new KeyedData(); for (int i = 0; i < 10000; i++) { string s = i.ToString(); var d = new Data { ID = s,Text = s }; dict.Add(d.ID,d); List.Add(d); keyd.Add(d); } var sw = new System.Diagnostics.Stopwatch(); sw.Start(); for (int r = 0; r < 1000; r++) { foreach (Data d in dict.Values) { if (null == d) throw new ApplicationException(); } } sw.Stop(); var dictTime = sw.ElapsedMilliseconds; sw.reset(); sw.Start(); for (int r = 0; r < 1000; r++) { foreach (Data d in keyd) { if (null == d) throw new ApplicationException(); } } sw.Stop(); var keydTime = sw.ElapsedMilliseconds; sw.reset(); sw.Start(); for (int r = 0; r < 1000; r++) { foreach (Data d in List) { if (null == d) throw new ApplicationException(); } } sw.Stop(); var ListTime = sw.ElapsedMilliseconds; Console.Writeline("Iterate whole collection"); Console.Writeline("Dict: " + dictTime); Console.Writeline("Keyd: " + keydTime); Console.Writeline("List: " + ListTime); sw.reset(); sw.Start(); for (int r = 0; r < 1000; r++) { for (int i = 0; i < 10000; i += 10) { string s = i.ToString(); Data d = dict[s]; if (null == d) throw new ApplicationException(); } } sw.Stop(); dictTime = sw.ElapsedMilliseconds; sw.reset(); sw.Start(); for (int r = 0; r < 1000; r++) { for (int i = 0; i < 10000; i += 10) { string s = i.ToString(); Data d = keyd[s]; if (null == d) throw new ApplicationException(); } } sw.Stop(); keydTime = sw.ElapsedMilliseconds; sw.reset(); sw.Start(); for (int r = 0; r < 10; r++) { for (int i = 0; i < 10000; i += 10) { string s = i.ToString(); Data d = List.FirstOrDefault(item => item.ID == s); if (null == d) throw new ApplicationException(); } } sw.Stop(); ListTime = sw.ElapsedMilliseconds * 100; Console.Writeline("Keyed search collection"); Console.Writeline("Dict: " + dictTime); Console.Writeline("Keyd: " + keydTime); Console.Writeline("List: " + ListTime); } }
}
更新:
@Blam建议的字典与KeyedCollection的比较.
最快的方法是迭代KeyedCollection项目数组.
但请注意,迭代字典值比KeyedCollection快,而不转换为数组.
请注意,迭代字典值比字典集合快得多.
Iterate 1,000 times over collection of 10,000 items Dictionary Pair: 519 ms Dictionary Values: 95 ms Dict Val ToArray: 92 ms KeyedCollection: 141 ms KeyedC. ToArray: 17 ms
计时来自windows控制台应用程序(发布版本).这是源代码:
using System;using System.Collections.Generic;using System.linq;namespace IterateCollections{ public class GUIDkeyCollection : System.Collections.ObjectModel.KeyedCollection<GuID,GUIDkey> { // This parameterless constructor calls the base class constructor // that specifIEs a dictionary threshold of 0,so that the internal // dictionary is created as soon as an item is added to the // collection. // public GUIDkeyCollection() : base() { } // This is the only method that absolutely must be overrIDden,// because without it the KeyedCollection cannot extract the // keys from the items. // protected overrIDe GuID GetKeyForItem(GUIDkey item) { // In this example,the key is the part number. return item.Key; } public GUIDkey[] ToArray() { return Items.ToArray(); } //[Obsolete("Iterate using .ToArray()",true)] //public new IEnumerator GetEnumerator() //{ // throw new NotImplementedException("Iterate using .ToArray()"); //} } public class GUIDkey : Object { private GuID key; public GuID Key { get { return key; } } public overrIDe bool Equals(Object obj) { //Check for null and compare run-time types. if (obj == null || !(obj is GUIDkey)) return false; GUIDkey item = (GUIDkey)obj; return (Key == item.Key); } public overrIDe int GetHashCode() { return Key.GetHashCode(); } public GUIDkey(GuID guID) { key = guID; } } class Program { static voID Main(string[] args) { const int itemCount = 10000; const int repetitions = 1000; const string resultFormat = "{0,18}: {1,5:D} ms"; Console.Writeline("Iterate {0:N0} times over collection of {1:N0} items",repetitions,itemCount); var dict = new Dictionary<GuID,GUIDkey>(); var keyd = new GUIDkeyCollection(); for (int i = 0; i < itemCount; i++) { var d = new GUIDkey(GuID.NewGuID()); dict.Add(d.Key,d); keyd.Add(d); } var sw = new System.Diagnostics.Stopwatch(); long time; sw.reset(); sw.Start(); for (int r = 0; r < repetitions; r++) { foreach (keyvaluePair<GuID,GUIDkey> w in dict) { if (null == w.Value) throw new ApplicationException(); } } sw.Stop(); time = sw.ElapsedMilliseconds; Console.Writeline(resultFormat,"Dictionary Pair",time); sw.reset(); sw.Start(); for (int r = 0; r < repetitions; r++) { foreach (GUIDkey d in dict.Values) { if (null == d) throw new ApplicationException(); } } sw.Stop(); time = sw.ElapsedMilliseconds; Console.Writeline(resultFormat,"Dictionary Values",time); sw.reset(); sw.Start(); for (int r = 0; r < repetitions; r++) { foreach (GUIDkey d in dict.Values.ToArray()) { if (null == d) throw new ApplicationException(); } } sw.Stop(); time = sw.ElapsedMilliseconds; Console.Writeline(resultFormat,"Dict Val ToArray",time); sw.reset(); sw.Start(); for (int r = 0; r < repetitions; r++) { foreach (GUIDkey d in keyd) { if (null == d) throw new ApplicationException(); } } sw.Stop(); time = sw.ElapsedMilliseconds; Console.Writeline(resultFormat,"KeyedCollection",time); sw.reset(); sw.Start(); for (int r = 0; r < repetitions; r++) { foreach (GUIDkey d in keyd.ToArray()) { if (null == d) throw new ApplicationException(); } } sw.Stop(); time = sw.ElapsedMilliseconds; Console.Writeline(resultFormat,"KeyedC. ToArray",time); } }}解决方法 使用秒表检查相对容易:
var d = new Dictionary<string,object>();var s = new List<object>();for (int i =0 ; i != 10000000 ; i++) { d.Add(""+i,i); s.Add(i);}var sw = new Stopwatch();sw.Start();foreach(object o in d.Values) { if (o == null) throw new ApplicationException();}sw.Stop();Console.Writeline(sw.ElapsedMilliseconds);sw.reset();sw.Start();foreach (object o in s) { if (o == null) throw new ApplicationException();}sw.Stop();Console.Writeline(sw.ElapsedMilliseconds);
这将打印相当接近的数字:
Dict List---- ---- 136 107 139 108 136 108
List总是获胜,但考虑到两个数据结构的相对复杂性,边距并不像人们预期的那么大.
总结以上是内存溢出为你收集整理的c# – 哪个.NET集合更快:枚举foreach Dictionary <>.值或List <>?全部内容,希望文章能够帮你解决c# – 哪个.NET集合更快:枚举foreach Dictionary <>.值或List <>?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)