只是一个快速查询:我有一段代码将一个字符串与一长串值进行比较,例如
if(str == "string1" || str == "string2" || str == "string3" || str == "string4".
DoSomething();
Run Code Online (Sandbox Code Playgroud)
代码清晰度和可维护性的兴趣我把它改成了
public static string[] strValues = { "String1", "String2", "String3", "String4"};
...
if(strValues.Contains(str)
DoSomething();
Run Code Online (Sandbox Code Playgroud)
只发现代码执行时间从2.5秒到6.8秒(执行大约200,000次).
我当然明白了一个轻微的表现权衡,但300%?
无论如何,我可以不同地定义静态字符串以提高性能?
干杯.
Rus*_*sty 16
据透露..
使用:
private static HashSet<string> strHashSet = new HashSet<string>()
{ "0string", "1string", "2string", "3string", "4string", "5string",
"6string", "7string", "8string", "9string", "Astring", "Bstring" };
private static List<string> strList = strHashSet.ToList();
private static string[] strArray = strList.ToArray();
private static Dictionary<int, string> strHashDict = strHashSet.ToDictionary(h => h.GetHashCode());
private static Dictionary<string, string> strDict = strHashSet.ToDictionary(h => h);
// Only one test uses this method.
private static bool ExistsInList(string str)
{
return strHashDict.ContainsKey(str.GetHashCode());
}
Run Code Online (Sandbox Code Playgroud)
检查列表中的第一个和最后一个字符串,然后检查不在列表中的字符串:"xstring"执行500,000次迭代,所有时间都以毫秒为单位.
1.A Test: result = (str == "0string" || str == "1string" ...
[storage var] [first]:[ last ]:[ none ]:[average]
strArray 3.78 : 45.90 : 57.77 : 35.82
2.A Test: ExistsInList(string);
[storage var] [first]:[ last ]:[ none ]:[average]
none 36.14 : 28.97 : 24.02 : 29.71
3.A Test: .ContainsKey(string.GetHashCode());
[storage var] [first]:[ last ]:[ none ]:[average]
strHashDict 34.86 : 28.41 : 21.46 : 28.24
4.A Test: .ContainsKey(string);
[storage var] [first]:[ last ]:[ none ]:[average]
strDict 38.99 : 32.34 : 22.75 : 31.36
5.A Test: .Contains(string);
[storage var] [first]:[ last ]:[ none ]:[average]
strHashSet 39.54 : 34.78 : 24.17 : 32.83
strList 23.36 : 122.07 : 127.38 : 90.94
strArray 350.34 : 426.29 : 426.05 : 400.90
6.A Test: .Any(p => p == string);
[storage var] [first]:[ last ]:[ none ]:[average]
strHashSet 75.70 : 331.38 : 339.40 : 248.82
strList 72.51 : 305.00 : 319.29 : 232.26
strArray 38.49 : 213.63 : 227.13 : 159.75
Run Code Online (Sandbox Code Playgroud)
当我们更改列表中的字符串时,会产生有趣的(如果不是意外的)结果:
private static HashSet<string> strHashSet = new HashSet<string>()
{ "string00", "string01", "string02", "string03", "string04", "string05",
"string06", "string07", "string08", "string09", "string10", "string11" };
Run Code Online (Sandbox Code Playgroud)
用"string99"作为无检查.
1.B Test: result = (str == "string00" || str == "string01" ...
[storage var] [first]:[ last ]:[ none ]:[average]
strArray 85.45 : 87.06 : 91.82 : 88.11
2.B Test: ExistsInList(string);
[storage var] [first]:[ last ]:[ none ]:[average]
none 30.12 : 27.97 : 21.36 : 26.48
3.B Test: .ContainsKey(string.GetHashCode());
[storage var] [first]:[ last ]:[ none ]:[average]
strHashDict 32.51 : 28.00 : 20.83 : 27.11
4.B Test: .ContainsKey(string);
[storage var] [first]:[ last ]:[ none ]:[average]
strDict 36.45 : 32.13 : 22.39 : 30.32
5.B Test: .Contains(string);
[storage var] [first]:[ last ]:[ none ]:[average]
strHashSet 37.29 : 34.33 : 23.56 : 31.73
strList 23.34 : 147.75 : 153.04 : 108.04
strArray 349.62 : 460.19 : 459.99 : 423.26
6.B Test: .Any(p => p == string);
[storage var] [first]:[ last ]:[ none ]:[average]
strHashSet 76.26 : 355.09 : 361.31 : 264.22
strList 70.20 : 332.33 : 341.79 : 248.11
strArray 37.23 : 234.70 : 251.81 : 174.58
Run Code Online (Sandbox Code Playgroud)
对于案例A和B看起来像测试2和3具有优势.
但是,HashSet.Contains(字符串)非常高效,不受列表内容的影响,并且具有清晰的语法......可能是最佳选择.
是的,这是真的,我没有生命.
您尝试过的两种方法都具有O(n)性能,因此当您添加更多字符串时它们会变慢.如果您使用的是.NET 3.5或更高版本,那么您可以尝试使用HashSet<string>替代版本并在应用程序开始时将其初始化一次.然后,您可以获得大约O(1)个查找.
对于.NET v2.0,您可以HashSet使用a 来模拟a Dictionary<string, object>并使用ContainsKey而不使用该值.
你在生产代码中实际运行了200,000次吗?如果是这样,您可能希望将哈希检查视为更快的否定检查.
如果200,000次只是为了说明差异,那我就不用担心了.它的时间仅增加0.02毫秒.
Contains比测试静态字符串更通用,因此存在少量开销.除非这个代码是Mark提到的瓶颈,否则不值得优化.CS中有一句名言:"过早优化是所有邪恶的根源." 报价不太准确,但它提醒了最终的优化指南:先测量.