我理解String和StringBuilder之间的区别(StringBuilder是可变的),但两者之间有很大的性能差异吗?

我正在工作的程序有很多case驱动的字符串追加(500+)。使用StringBuilder是更好的选择吗?


当前回答

使用字符串进行连接会导致运行时复杂度达到O(n^2)的量级。

如果使用StringBuilder,需要复制的内存就会少得多。使用StringBuilder(int capacity),如果您可以估计最终字符串的大小,则可以提高性能。即使不精确,也可能只需要将StringBuilder的容量增加几倍,这也有助于提高性能。

其他回答

StringBuilder减少了分配和赋值的数量,代价是使用了额外的内存。如果使用得当,它可以完全消除编译器需要一遍又一遍地分配越来越大的字符串,直到找到结果为止。

string result = "";
for(int i = 0; i != N; ++i)
{
   result = result + i.ToString();   // allocates a new string, then assigns it to result, which gets repeated N times
}

vs.

String result;
StringBuilder sb = new StringBuilder(10000);   // create a buffer of 10k
for(int i = 0; i != N; ++i)
{
   sb.Append(i.ToString());          // fill the buffer, resizing if it overflows the buffer
}

result = sb.ToString();   // assigns once

从内存的角度来看,StringBuilder的性能会更好。至于处理,执行时间的差异可以忽略不计。

一个简单的例子来演示使用String连接和StringBuilder在速度上的差异:

System.Diagnostics.Stopwatch time = new Stopwatch();
string test = string.Empty;
time.Start();
for (int i = 0; i < 100000; i++)
{
    test += i;
}
time.Stop();
System.Console.WriteLine("Using String concatenation: " + time.ElapsedMilliseconds + " milliseconds");

结果:

使用字符串串联:15423毫秒

StringBuilder test1 = new StringBuilder();
time.Reset();
time.Start();
for (int i = 0; i < 100000; i++)
{
    test1.Append(i);
}
time.Stop();
System.Console.WriteLine("Using StringBuilder: " + time.ElapsedMilliseconds + " milliseconds");

结果:

使用StringBuilder: 10毫秒

结果,第一次迭代花费了15423毫秒,而使用StringBuilder的第二次迭代花费了10毫秒。

在我看来,使用StringBuilder更快,快得多。

以“微优化剧场的悲剧”为例。

StringBuilder是可取的,如果你正在做多个循环,或分叉在你的代码传递…然而,对于PURE性能,如果你可以使用SINGLE字符串声明,那么性能就会更好。

例如:

string myString = "Some stuff" + var1 + " more stuff"
                  + var2 + " other stuff" .... etc... etc...;

更有表现力吗

StringBuilder sb = new StringBuilder();
sb.Append("Some Stuff");
sb.Append(var1);
sb.Append(" more stuff");
sb.Append(var2);
sb.Append("other stuff");
// etc.. etc.. etc..

在这种情况下,可以认为StringBuild更易于维护,但性能并不比单个字符串声明更好。

但是十有八九……使用字符串构建器。

另一方面:string + var也比string的性能更好。格式方法(通常)在内部使用StringBuilder(如果有疑问…检查反射器!)