是String.Contains()比String.IndexOf()快吗?


111

我有大约2000个字符的字符串缓冲区,需要检查缓冲区是否包含特定的字符串。
将针对每个Web请求在ASP.NET 2.0 Web应用程序中进行检查。

有人知道String.Contains方法是否比String.IndexOf方法执行得更好吗?

    // 2000 characters in s1, search token in s2
    string s1 = "Many characters. The quick brown fox jumps over the lazy dog"; 
    string s2 = "fox";
    bool b;
    b = s1.Contains(s2);
    int i;
    i = s1.IndexOf(s2);

有趣的事实


14
如果您需要针对每个Web请求执行十亿次操作,那么我将开始研究类似的内容。在任何其他情况下,我都不会打扰,因为与首先接收HTTP请求相比,使用这两种方法所花费的时间很可能微不足道。
mookid8000,2009年

2
优化的关键之一是测试而不是假设,因为它可能取决于许多因素,例如.NET版本,操作系统,硬件,输入的变化等。在许多情况下,测试结果是由其他人完成的在您的系统上可能会非常不同。
斯莱

Answers:


174

Contains电话IndexOf

public bool Contains(string value)
{
    return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}

哪个调用CompareInfo.IndexOf,最终使用CLR实现。

如果要查看如何在CLR中比较字符串,这将向您显示(查找CaseInsensitiveCompHelper)。

IndexOf(string)没有选项,Contains()而是使用序数比较(逐字节比较,而不是尝试执行智能比较,例如,使用é与é)。

因此IndexOf(从理论上来说)将稍微快一些IndexOf,直接使用kernel32.dll中的FindNLSString进行字符串搜索(反射器的功能!)。

更新了.NET 4.0 - 的IndexOf不再使用序号比较等都含有可以更快。请参阅下面的评论。


3
这个答案
远远不

55
我的答案已有7年历史,并且基于.NET 2框架。版本4 IndexOf()确实可以使用,StringComparison.CurrentCulture并且Contains()使用StringComparison.Ordinal速度会更快。但是实际上,我们所讨论的速度差异是微小的-一点是一个调用另一个,而如果您不需要索引,Contains更具可读性。换句话说,不用担心。
克里斯·S

21

可能根本不重要。阅读有关编码恐怖的帖子;):http : //www.codinghorror.com/blog/archives/001218.html


4
吸吮老板是我们吗?:D不过,与处理http请求所花费的时间相比,您一次是对的,一次搜索短字符串并不重要。
禽鸟

一个有趣的读物,但令我烦恼的是,最初对串联的抱怨是对内存的使用,然后他只测试了用各种方式组合字符串所花费的时间。
sab669 2013年

11

Contains(s2)比IndexOf(s2)快很多倍(在我的计算机中是10倍),因为Contains使用StringComparison.Ordinal快于默认情况下IndexOf进行的区域性敏感搜索(但在.net 4.0 http中可能会更改: //davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx)。

在我的测试中,Contains具有与IndexOf(s2,StringComparison.Ordinal)> = 0完全相同的性能,但它的长度较短,可以使您的意图明确。


2
.NET 4.0的更改在进入RTM之前显然已经恢复,因此我不会过多地依赖该文章blogs.msdn.com/bclteam/archive/2008/11/04/…–
Stephen Kennedy

7

我正在运行一个实际案例(与综合基准相反)

 if("=,<=,=>,<>,<,>,!=,==,".IndexOf(tmps)>=0) {

 if("=,<=,=>,<>,<,>,!=,==,".Contains(tmps)) {

这是我系统的重要组成部分,它执行了131,953次(感谢DotTrace)。

然而令人惊讶的是,结果却与预期相反

  • 索引:533ms。
  • 包含266ms。

:-/

网络框架4.0(于2012年2月13日更新)


1
因为INT它比更大BOOL,并IndexOf>=0导致更远的一步
埃里克·尹

3
您忘了使用“ StringComparison.Ordinal”
Davi Fiamenghi 2013年

6

通过使用Reflector,您可以看到,包含是使用IndexOf实现的。这是实现。

public bool Contains(string value)
{
   return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}

因此,Contains可能比直接调用IndexOf慢一点,但是我怀疑它对实际性能没有任何意义。


1
是的,但是要使用indexof作为布尔值,他将不得不在函数外部进行比较。那很可能会产生与Contains相同的结果,不是吗?
贡萨洛·奎罗,

1
可能,但是您确实保存了一个方法调用(除非可以内联)。正如我所说,这可能永远不会有意义。
布赖恩·拉斯穆森

6

如果您真的想对代码进行微优化,那么最好的方法就是始终进行基准测试。

.net框架具有出色的秒表实现-System.Diagnostics.Stopwatch


最好,但是如果您想快速使用,只需在调试会话中按暂停按钮即可。代码控制可能会在最慢的部分中停止大约50%的时间
杰里米·汤普森

4

通过一些阅读,似乎可以发现String.Contains方法只是简单地调用String.IndexOf。区别在于String.Contains返回一个布尔值,而String.IndexOf返回一个带有(-1)的整数,表示未找到子字符串。

我建议编写一个带有100,000次左右迭代的小测试,然后自己看看。如果我猜的话,我会说IndexOf可能会更快一些,但是就像我说的那样,只是一个猜测。

杰夫·阿特伍德(Jeff Atwood)在他的博客上有一篇关于弦的文章。它更多地是关于级联的,但是可能会有所帮助。


3

正如对此的更新一样,我一直在进行一些测试,并提供相当大的输入字符串,然后并行Regex是我发现的最快的C#方法(假设您拥有多个我想象的核心)

获取匹配总数,例如-

needles.AsParallel ( ).Sum ( l => Regex.IsMatch ( haystack , Regex.Escape ( l ) ) ? 1 : 0 );

希望这可以帮助!


1
嗨,phild在一个单独的线程上使用tomasp.net/articles/ahocorasick.aspx中的版本进行了更新,该版本可以使您的关键字(针)保持不变,这要快得多。
加里2010年

2

使用基准库(例如Jon Skeet最近进行的尝试)来对其进行度量。

买者自负

作为所有(微)性能问题,这取决于您使用的软件版本,检查的数据的详细信息以及调用周围的代码。

由于所有(微)性能问题,第一步必须是获得易于维护的运行版本。然后可以将基准测试,性能分析和调整应用于所测量的瓶颈,而不用进行猜测。


尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接的页面发生更改,仅链接的答案可能会失效。
2014年

链接库只是众多库中的一种,而不是答案的主要目的。我认为发布图书馆资源或描述不会改善答案,该站点或整个世界。
David Schmitt

3
-1; 问题是“有人知道String.Contains方法是否比String.IndexOf方法执行得更好吗?” -您的答案是“使用基准库”,基本上表示“我不知道,自己做”,“这取决于”,意思是“我不知道”和“获取运行的版本和配置文件” ,也表示“我不知道,自己做”。这不是'Jeopardy'-请提供所回答 问题的答案,而不是指导 思想 -它们在注释中的位置

-7

对于仍在阅读本文的任何人,由于contains()与IE不兼容,indexOf()在大多数企业系统上可能会表现更好。


11
抛出新的OutOfScopeException();
拉斐尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.