我有一种情况,我需要连接几个字符串以形成一个类的id。基本上我只是循环一个列表来获取对象的ToString值然后连接它们。
foreach (MyObject o in myList)
result += o.ToString();
该列表预计不会有超过5个元素(虽然它可以但这是一个非常非常简单的情况)并且通常会有1到3个元素,通常只有一个或两个元素。
什么是更好的性能,保持连接或使用StringBuilder?
StringBuilder bld = new StringBuilder()
foreach (MyObject o in myList)
bld.Append(o.ToString());
我不确定在最常见的情况下,创建StringBuilder是否会花费比标准串联更多的时间。
这是懒惰的,列表中的项目一旦创建就不会改变,因此在调用时,id会被懒惰地构造一次。
作为旁注......我应该使用固定数组而不是List吗?如果我这样做,我会得到任何性能或内存改进吗? (列表仅用作IEnumerable)
问题的一般观点可能是,有多少字符串足以阻止连接并开始构建?
我是否应该费心去测试情景?
if (myList.Count > 4)
ConcatWithStringBuilder(myList);
答案 0 :(得分:32)
通常的答案是字符串连接对于4到8个字符串更有效。这取决于你阅读的博客。
不要编写测试来决定使用哪种方法。如果你不确定它是否会超过魔法限制,那么只需使用StringBuilder。
运行此代码以查看自己的结果:
const int sLen=30, Loops=5000;
DateTime sTime, eTime;
int i;
string sSource = new String('X', sLen);
string sDest = "";
//
// Time string concatenation.
//
sTime = DateTime.Now;
for(i=0;i<Loops;i++) sDest += sSource;
eTime = DateTime.Now;
Console.WriteLine("Concatenation took " + (eTime - sTime).TotalSeconds + " seconds.");
//
// Time StringBuilder.
//
sTime = DateTime.Now;
System.Text.StringBuilder sb = new System.Text.StringBuilder((int)(sLen * Loops * 1.1));
for(i=0;i<Loops;i++) sb.Append(sSource);
sDest = sb.ToString();
eTime = DateTime.Now;
Console.WriteLine("String Builder took " + (eTime - sTime).TotalSeconds + " seconds.");
//
// Make the console window stay open
// so that you can see the results when running from the IDE.
//
Console.WriteLine();
Console.Write("Press Enter to finish ... ");
Console.Read();
答案 1 :(得分:13)
我支持保持简单的想法,直到你有充分的理由让它们变得复杂。
对于像2-5元素这样的东西,使用StringBuilder是没有意义的(除非你连续重复这个连接)。更好的可读语法“+ =”具有更多价值。
答案 2 :(得分:4)
问题的一般观点可能是,有多少字符串足以阻止连接并开始构建?
这取决于字符串的长度,如果您可以预测目标长度,那么您应该为StringBuilder
构造函数提供长度,如果您将它们连接在一起或在几个步骤。
如果您一次连接它们(例如s = "A" + "b" + "c" + "d"
),那么使用StringBuilder
可能永远不会有意义。
如果你可以准确地预测长度,那么即使对于3个字符串,StringBuilder也会更快。
如果你有超过5个concats,通常StringBuilder会更快。但即便如此,仅仅连接字符串通常也几乎没有开销(除非它以紧密的循环运行)。
一旦使用StringBuilder
达到10个小结,可能会有利。
编辑:只是为了说清楚:在你的情况下,你应该明确没有StringBuilder
。
答案 3 :(得分:4)
为什么你不能只使用
String.Concat(myList)
而不是重新发明轮子? 它具有很高的性能,但却很简单 更多信息:http://msdn.microsoft.com/en-us/library/system.string.concat.aspx
答案 4 :(得分:2)
IMO字符串连接更具可读性。你使用+和+ =而不是strBldInstance.Add(),这可能会使代码更加混乱,
StringBuilder的存在是为了使串联更具性能,更多,但我通常会为了代码可读性而牺牲性能。如果你在这里和那里捕捉一些字符串,你的代码不会受到影响。对于经常捕获许多字符串的代码块,请使用StringBuilder。
答案 5 :(得分:0)
在这种情况下,字符串构建器很可能会稍微快一些,但实际上它可能不足以让人烦恼。它实际上取决于两件事,你重新创建字符串的次数(因为字符串是不可变的,并且连接强制从现有的两个字符串创建一个新的字符串),以及字符串元素的大小你正在联合起来。连接五个字符串(每个字符串为2个字节)将非常不同于将5个字符串连接在一起,每个字符串为5000字节,因为字符串越长,系统分配内存和垃圾收集对象的工作就越多使用时间更长。字符串生成器是一个更好的选择,因为它已经被优化以将字符串连接在一起,并且您不必担心性能因素。
考虑到所有这一切,如果您知道字符串最终的最终大小有多大,字符串构建器几乎肯定会更快。当你告诉它为最终字符串分配多少内存时,它不必经历重新分配内存的过程。
答案 6 :(得分:0)
如果你可以估计将用于完整字符串的字节数(并使用它来初始化StringBuilder的容量),那么当执行超过大约3次的concats时,StringBuilder可能会胜过String类。
答案 7 :(得分:0)
我之所以使用StringBuilder只是因为你希望在整个应用程序中保持一致。实例化Java / .NET对象也不费时,尽管我猜想在StringBuilder设置时会有一些内务处理。肯定比通过串联创建多个String对象更糟糕。
答案 8 :(得分:0)
如果可以的话,你可以获得一些乐趣并完全取消for循环并使用聚合?
var concatstring = mylist.Aggregate("", (acc, item) => acc + "." + item);
不确定这个的开销吗?
答案 9 :(得分:0)
在解决leetcode问题时发现了这个(性能)主题。 对于具有大于或等于42k个字符的字符串,出于某种原因,stringBuilder速度更快。
我下面的代码在StringBuilder中以指定的大小写(> 42k个字符)来反转字符串。
TRUE
,但同一功能不适用于字符串连接,即 toReturn + = s [i] 。