最近我发现自己使用StringBuilder进行所有字符串连接,无论大小,但是在最近的性能测试中,我换了一个同事的 stringOut = string1 +“。” string2 样式连接(用于每次新建StringBuilder的10000x +循环),用于StringBuilder只是为了看看它在次要连接中会有什么不同。
我发现,在性能测试的许多次运行中,无论是串联还是StringBuilder,更改都无论是更高还是更低(重申这是小型连接)。
StringBuilder对象的'newing up'在什么时候否定了使用它的好处?
答案 0 :(得分:20)
我遵循的规则是 -
在编译时未知连接数时使用StringBuilder。
因此,在您的情况下,每个StringBuilder只会附加几次然后被丢弃。这与
之类的东西并不相同string s = String.Empty;
for (int i = 0; i < 10000; ++i)
{
s += "A";
}
使用StringBuilder会大大提高性能,因为否则会不断分配新的内存。
答案 1 :(得分:18)
我确信我已经找到了另一个答案,我只发布了link to my article然后发布了摘要,但是我们再来一次。
当您在一个非平凡的循环中连接时,肯定会使用StringBuilder
- 特别是如果您不确定(在编译时)您将通过循环进行多少次迭代。例如,一次读取一个文件,使用+ =运算符构建一个字符串可能会导致性能自杀。
当你可以(可读地)指定需要在一个语句中连接的所有内容时,绝对使用连接运算符。 (如果要连接一系列事物,请考虑明确调用String.Concat
- 或者如果需要分隔符则调用String.Join
。)
不要害怕将文字分成几个连接位 - 结果将是相同的。例如,你可以通过将长文字分成几行来提高可读性,而不会损害性能。
如果您需要连接的中间结果而不是提供下一次连接迭代,StringBuilder
将无法帮助您。例如,如果您从名字和姓氏建立一个全名,然后在最后添加第三条信息(可能是昵称),那么只有使用StringBuilder
才能获益您不需要(名字+姓氏)字符串用于其他目的(正如我们在创建Person
对象的示例中所做的那样)。
如果您只是要进行一些连接,并且您真的想在单独的语句中进行这些连接,那么您走哪条路并不重要。哪种方式更有效将取决于所涉及的字符串大小的串联数量,以及它们连接的顺序。如果您确实认为该段代码是性能瓶颈,则可以两种方式进行配置或基准测试。
答案 2 :(得分:6)
有时值得查看documentation:
串联的表现 String或的操作 StringBuilder对象取决于方式 通常会发生内存分配。一个 字符串连接操作始终 分配内存,而a StringBuilder连接操作 只有分配内存 StringBuilder对象缓冲区也是如此 小到容纳新数据。 因此,String类是 最好是串联 操作如果是固定数量的String 对象是连接的。在那里面 个案,个别串联 甚至可以将操作合并到一起 编译器的单个操作。一个 StringBuilder对象更适合 一个连接操作,如果一个 任意数量的字符串 级联;例如,如果一个循环 连接随机数 用户输入字符串。
在您的示例中,每个输出字符串只有一个连接,因此StringBuilder不会获得任何结果。如果要多次添加相同字符串,则应使用StringBuilder,例如:
stringOut = ...
for(...)
stringOut += "."
stringOut += string2
答案 3 :(得分:2)
我的经验法则很简单。
+
。根据我的经验,表达式如:
"Id: " + item.id + " name: " + item.name
可以比以下更容易编写和理解:
StringBuilder sb = new StringBuilder();
sb.append("Id: ").append(item.id);
sb.append(" name: ").append(item.name);
(然后使用来自sb
的字符串,其中上面的表达式已被写入),并且它的表现同样出色(提示:查看编译后的代码以了解原因!)
另一方面,当需要随着时间的推移(当程序运行时)或空间(由来自代码的不同部分的值组成)累积字符串时,以一种单独写入的方式是不切实际的-line表达式,然后StringBuilder避免了:
的开销(时间和内存流失)String s = somethingExpression;
...
s += someOtherExpression;
...
s += yetAnotherExpression;
...
答案 4 :(得分:1)
来自MSDN:
[T]他的字符串类更适合a 连接操作如果是固定的 String对象的数量是 级联。在那种情况下, 个别连接操作 甚至可以组合成一个单一的 由编译器操作。一个 StringBuilder对象更适合 一个连接操作,如果一个 任意数量的字符串 级联;例如,如果一个循环 连接随机数 用户输入字符串。
我想答案是“它取决于” - 如果你在一个循环内连接超过一些迭代,那么StringBuilder几乎总能提供更好的性能,但唯一可以确定的方法是实际剖析
答案 5 :(得分:1)
Coding Horror上有一篇有趣的文章。 Jeff在双核3.5 GHz Core 2 Duo上获得了以下100,000次迭代的结果:
Simple Concatenation - 606 ms
String.Format - 665 ms
string.Concat - 587 ms
String.Replace - 979 ms
StringBuilder - 588 ms
答案 6 :(得分:1)
何时使用StringBuilder?
StringBuilder完全是一种优化,除了内部实现之外,它不对字符串Concat进行逻辑改进。也就是说,在高性能应用程序和网站中正确使用它至关重要。
有时,使用简单的字符串Concats可以使用4次或更少次迭代的小循环。但是,在边缘情况下,这可能是灾难性的。使用StringBuilder计划边缘情况。