字符串vs.StringBuilder

时间:2020-03-05 18:56:22  来源:igfitidea点击:

我了解StringStringBuilder之间的区别(StringBuilder是可变的),但是两者之间在性能上有很大的不同吗?

我正在开发的程序具有很多大小写驱动的字符串追加(500+)。使用StringBuilder是更好的选择吗?

解决方案

回答

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

回答

我相信,如果我们需要将4个以上的字符串添加在一起,则StringBuilder会更快。另外,它还可以做一些很棒的事情,例如AppendLine。

回答

在.NET中,StringBuilder仍然比添加字符串快。我很确定在Java中,当我们添加字符串时,它们只是在幕后创建了一个StringBuffer,因此并没有什么区别。我不确定为什么他们还没有在.NET中做到这一点。

回答

是的,性能差异很大。请参见知识库文章"如何在Visual C#中改善字符串连接性能"。

我一直试图先为清晰起见编写代码,然后再为性能进行优化。这比其他方法要容易得多!但是,在看到我的应用程序在两者之间存在巨大的性能差异之后,我现在要更加仔细地考虑它。

幸运的是,在代码上运行性能分析以了解我们在哪里花费时间,然后在需要时对其进行修改以使用StringBuilder相对简单。

回答

StringBuilder可能更可取。原因是它分配的空间超过了当前所需的空间(我们设置了字符数),为将来的追加留出了空间。然后,那些适合当前缓冲区的将来的追加不需要任何内存分配或者垃圾回收,这可能会很昂贵。通常,我使用StringBuilder进行复杂的字符串连接或者多种格式,然后在数据完成后将其转换为普通的String,并且我再次想要一个不可变的对象。

回答

如果我们要进行大量的字符串连接,请使用StringBuilder。与字符串连接时,每次都会创建一个新的字符串,从而消耗更多的内存。

亚历克斯

回答

除了前面的答案,考虑此类问题时,我总是做的第一件事就是创建一个小型测试应用程序。在此应用程序内,针对这两种情况执行一些时序测试,然后亲自查看哪个更快。

恕我直言,追加500多个字符串条目肯定应该使用StringBuilder。

回答

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

如果使用StringBuilder,那么要做的内存复制要少得多。如果可以估计最终String的大小,可以使用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
}

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

回答

我的方法一直是在连接4个或者更多字符串时使用StringBuilder
或者
当我不知道如何进行级联时。

此处有关性能良好的文章

回答

实际上,String和StringBuilder都是不可变的,StringBuilder内置了缓冲区,可以更有效地管理其大小。需要何时调整StringBuilder的大小是在堆上重新分配StringBuilder的时间。默认情况下,它的大小为16个字符,我们可以在构造函数中进行设置。

例如。

StringBuilder sb =新的StringBuilder(50);

回答

为了澄清吉利安所说的关于4弦的话,如果我们有这样的话:

string a,b,c,d;
 a = b + c + d;

那么使用字符串和加号运算符会更快。这是因为(就像Eric所指出的Java一样),它在内部自动使用StringBuilder(实际上,它使用StringBuilder也使用的原语)

但是,如果我们正在做的事情更接近:

string a,b,c,d;
 a = a + b;
 a = a + c;
 a = a + d;

然后,我们需要显式使用StringBuilder。 .Net不会在这里自动创建StringBuilder,因为它毫无意义。在每一行的末尾," a"必须是一个(不可变的)字符串,因此它必须在每一行上创建并放置一个StringBuilder。为了提高速度,我们需要使用相同的StringBuilder直到完成构建:

string a,b,c,d;
StringBuilder e = new StringBuilder();
 e.Append(b);
 e.Append(c);
 e.Append(d);
 a = e.ToString();

回答

此基准表明,合并3个或者更少的字符串时,常规串联速度更快。

http://www.chinhdo.com/20070224/stringbuilder-is-not-always-faster/

StringBuilder可以显着提高内存使用率,尤其是在将500个字符串加在一起的情况下。

考虑以下示例:

string buffer = "The numbers are: ";
for( int i = 0; i < 5; i++)
{
    buffer += i.ToString();
}
return buffer;

内存中会发生什么?将创建以下字符串:

1 - "The numbers are: "
2 - "0"
3 - "The numbers are: 0"
4 - "1"
5 - "The numbers are: 01"
6 - "2"
7 - "The numbers are: 012"
8 - "3"
9 - "The numbers are: 0123"
10 - "4"
11 - "The numbers are: 01234"
12 - "5"
13 - "The numbers are: 012345"

通过将这五个数字添加到字符串的末尾,我们创建了13个字符串对象!其中有12个毫无用处!哇!

StringBuilder解决了此问题。它不是我们经常听到的"可变字符串"(.NET中的所有字符串都是不可变的)。它通过保留一个内部缓冲区(一个char数组)来工作。调用Append()或者AppendLine()会将字符串添加到char数组末尾的空白处。如果数组太小,它将创建一个更大的新数组,并在此复制缓冲区。因此,在上面的示例中,StringBuilder可能只需要一个数组即可包含所有5个字符串添加项,具体取决于其缓冲区的大小。我们可以告诉StringBuilder它的缓冲区在构造函数中应该有多大。

回答

我已经看到在将StringBuilder实例用于任何字符串存储之前,对StringBuilder实例使用EnCapCapacity(int capacity)方法可显着提高性能。我通常在实例化之后在代码行中调用它。就像实例化StringBuilder一样,具有相同的效果:

var sb = new StringBuilder(int capacity);

该调用会提前分配所需的内存,这将导致在多次" Append()"操作期间较少的内存分配。我们必须对需要多少内存做出有根据的猜测,但是对于大多数应用程序来说,这应该不太困难。我通常会在内存过多方面犯错(我们正在谈论1k左右)。

回答

不要盲目追求StringBuilder。在某些情况下,StringBuilder无法提高性能。

Rico Mariani为此写了两个有见地的博客文章:

http://blogs.msdn.com/ricom/archive/2003/12/02/40778.aspx

http://blogs.msdn.com/ricom/archive/2003/12/15/43628.aspx

回答

如果我们要执行多个循环或者在代码传递中进行派生,则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也比在内部使用StringBuilder的string.Format方法(通常)具有更高的性能(如有疑问,请检查反射器!)

回答

字符串连接将花费更多。
在Java中,我们可以根据需要使用StringBuffer或者StringBuilder。
如果我们想要同步且线程安全的实现,请使用StringBuffer。这将比String串联更快。

如果不需要同步或者线程安全的实现,请使用StringBuilder。
这将比String串联快,也比StringBuffer快,因为它们没有同步开销。

回答

作为一般经验法则,如果我必须多次设置字符串的值,或者该字符串有任何追加,那么它就必须是一个字符串生成器。在了解字符串构建器之前,我曾经看过我写过的应用程序,这些构建器具有巨大的内存足迹,而且似乎还在不断增长。更改这些程序以使用字符串生成器可以显着减少内存使用。现在,我向字符串生成器发誓。

回答

StringBuilder更适合从许多非常数值构建一个字符串。

如果要从许多常量值中构建字符串,例如HTML或者XML文档中的多行值或者其他文本块,则只需添加到同一字符串即可,因为几乎所有编译器都可以这样做"常量折叠",这是在我们进行一堆常量操作时减少解析树的过程(当我们编写类似int minutesPerYear = 24 * 365 * 60之类的内容时,也会使用该过程)。对于带有非恒定值的简单情况,.NET编译器会将代码简化为类似于StringBuilder所做的事情。

但是当编译器无法将追加内容简化为更简单的内容时,我们将需要一个StringBuilder。正如fizch指出的那样,这种情况更有可能在循环内发生。

回答

考虑"微型优化剧院的悲剧"。

回答

The performance of a concatenation operation for a String or StringBuilder object depends on how often a memory allocation occurs. A String concatenation operation always allocates memory, whereas a StringBuilder concatenation operation only allocates memory if the StringBuilder object buffer is too small to accommodate the new data. Consequently, the String class is preferable for a concatenation operation if a fixed number of String objects are concatenated. In that case, the individual concatenation operations might even be combined into a single operation by the compiler. A StringBuilder object is preferable for a concatenation operation if an arbitrary number of strings are concatenated; for example, if a loop concatenates a random number of strings of user input.

资料来源:MSDN