昨天来了一位顾问,不知何故,字符串的话题出现了。他提到,他已经注意到,对于长度小于一定长度的字符串,Contains实际上比StartsWith更快。我不得不亲眼看到它,所以我写了一个小应用程序,果然,Contains更快!
这怎麽可能?
DateTime start = DateTime.MinValue;
DateTime end = DateTime.MinValue;
string str = "Hello there";
start = DateTime.Now;
for (int i = 0; i < 10000000; i++)
{
str.Contains("H");
}
end = DateTime.Now;
Console.WriteLine("{0}ms using Contains", end.Subtract(start).Milliseconds);
start = DateTime.Now;
for (int i = 0; i < 10000000; i++)
{
str.StartsWith("H");
}
end = DateTime.Now;
Console.WriteLine("{0}ms using StartsWith", end.Subtract(start).Milliseconds);输出:
726ms using Contains
865ms using StartsWith我也尝试过使用更长的字符串!
发布于 2010-06-26 01:34:53
尝试使用StopWatch而不是DateTime检查来测量速度。
Stopwatch vs. using System.DateTime.Now for timing events
我认为关键是以下重要的部分加粗了:
Contains
此方法执行区分大小写和culture-insensitive)比较的顺序比较(
)。
StartsWith
此方法使用当前区域性执行区分大小写和culture-sensitive)的word比较。
我认为关键是序数比较,它相当于:
序号排序根据字符串中每个Char对象的数值比较字符串。序号比较自动区分大小写,因为字符的小写和大写版本具有不同的代码点。但是,如果大小写在应用程序中不重要,则可以指定忽略大小写的序号比较。这相当于使用不变区域性将字符串转换为大写,然后对结果执行序号比较。
参考文献:
http://msdn.microsoft.com/en-us/library/system.string.aspx
http://msdn.microsoft.com/en-us/library/dy85x1sa.aspx
http://msdn.microsoft.com/en-us/library/baketfxw.aspx
使用Reflector,你可以看到这两个的代码:
public bool Contains(string value)
{
return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}
public bool StartsWith(string value, bool ignoreCase, CultureInfo culture)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (this == value)
{
return true;
}
CultureInfo info = (culture == null) ? CultureInfo.CurrentCulture : culture;
return info.CompareInfo.IsPrefix(this, value,
ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
}发布于 2010-06-26 01:35:13
我想通了。这是因为StartsWith是文化敏感的,而Contains不是。这本质上意味着StartsWith必须做更多的工作。
FWIW,这是我在Mono上的结果,使用以下(更正后的)基准:
1988.7906ms using Contains
10174.1019ms using StartsWith我很高兴看到人们在MS上的结果,但我的主要观点是,正确地完成了(并假设类似的优化),我认为StartsWith必须更慢:
using System;
using System.Diagnostics;
public class ContainsStartsWith
{
public static void Main()
{
string str = "Hello there";
Stopwatch s = new Stopwatch();
s.Start();
for (int i = 0; i < 10000000; i++)
{
str.Contains("H");
}
s.Stop();
Console.WriteLine("{0}ms using Contains", s.Elapsed.TotalMilliseconds);
s.Reset();
s.Start();
for (int i = 0; i < 10000000; i++)
{
str.StartsWith("H");
}
s.Stop();
Console.WriteLine("{0}ms using StartsWith", s.Elapsed.TotalMilliseconds);
}
}发布于 2013-05-03 05:36:00
当涉及到文化敏感问题时,StartsWith和Contains的表现完全不同。
特别是,返回true的StartsWith并不意味着返回true的Contains。只有当你真的知道自己在做什么的时候,你才应该用另一个替换。
using System;
class Program
{
static void Main()
{
var x = "A";
var y = "A\u0640";
Console.WriteLine(x.StartsWith(y)); // True
Console.WriteLine(x.Contains(y)); // False
}
}https://stackoverflow.com/questions/3120056
复制相似问题