最有效的连接字符串的方式

我需要连接很多字符串并在其中任何一个之间加上逗号。 我有一个字符串列表

"123123123213" "1232113213213" "123213123" 

而且我想得到

 "123123123213,1232113213213,123213123" 

我想知道实现这一目标的最佳方法是什么。

我可以这样做:

 private List stringList = new List { // a lot of strings in here "1234567890", "34343434", "4343434" }; string outcome = string.Join(",", stringList.ToArray()); 

或者可能:

 StringBuilder builder = new StringBuilder(); stringList.ForEach(val => { builder.Append(val); builder.Append(","); }); string outcome = builder.ToString(); 

哪种方式更好? 你知道连接字符串的更好方法吗?

正如@Ekkehard所说,使用string.Join 。

但是,您不需要ToArray()因为string.Join具有IEnumerable的重载。

 List stringList = new List { "1234567890", "34343434", "4343434" }; string outcome = string.Join(",", stringList); 

编辑

正如@Kobi所说,这只适用于C#4.0。 在3.5我会这样做。

 var s = new StringBuilder(stringList.Count * 8); foreach (var item in stringList) { s.Append(item); s.Append(','); } s.Length -= 1; string outcome = stringList.ToList(); 

你应该使用string.Join()因为:

a)它的可读性,可维护性和易用性。

b)它内部已经使用了StringBuilder ,所以它非常有效(你可以使用Reflector确认自己)。

编辑:

string.Join()使用StringBuilder作为IEnumerable输入的一般情况。 如果你已经拥有一个数组,那么它使用一些巫术魔法(包括FastAllocateString()UnSafeCharBuffer )甚至更快。

使用Join,因为它不会添加尾随“,”。

这个页面上有一个基准测试,似乎表明在很多迭代中, string.Join在一个小数组上的性能优于StringBuilder 。 您也应该对较大的arrays进行基准测试。 正如我发布的那样,我看到BrokenGlass回答说StringBuilder是在string.Join内部使用的,所以你可以期待它更快。

最后,你的第二个解决方案增加了额外的解决方案 看看Eric Lippert的博客文章

我建议修复你的第二个解决方案。 StringBuilder肯定会更快,因为您避免将列表内容复制到新数组。

 StringBuilder builder = new StringBuilder(); string separator = ""; stringList.ForEach( val => { builder.Append(separator).Append(val); separator = ","; }); string outcome = builder.ToString(); 

StringBuilder是一种非常有效的方法,在这里推荐使用。

根据我做的以下测试, Join在大型arrays上的速度提高3倍

Text.txt文件包含38400行的值"aaaaaaaaaaaaaaaaaaa"

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Diagnostics; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var strings = File.ReadAllLines("Text.txt"); Stopwatch sw; StringBuilder sb = new StringBuilder(); sw = Stopwatch.StartNew(); for (int i = 0; i < strings.Length; i++) { sb.AppendLine(strings[i]); } sw.Stop(); TimeSpan sbTime = sw.Elapsed; sw = Stopwatch.StartNew(); var output = string.Join(",", strings); sw.Stop(); TimeSpan joinTime = sw.Elapsed; } } } 

输出:

 00:00:00.0098754 00:00:00.0032922 

如果要加入固定数量的字符串, String.Join是最快的。 更深层次的原因是String.Join循环遍历数组并分配具有正确大小的最终字符串缓冲区,因为它在第一遍中将所有字符串的字符串长度添加到一起。 当您使用StringBuilder及其容量时,您可以获得类似的结果。 黄金法则是以两次循环数组为代价来节省内存分配。 哪种方法更快取决于列表中有多少项以及resultint字符串的大小。

你的,Alois Kraus

测试代码:

 public static void Performance(Action fn) { var timer = new Stopwatch(); timer.Start(); for (var i = 0; i < 10000000; ++i) { fn(); } timer.Stop(); Console.WriteLine("{0} Time: {1}ms ({2})", fn.ToString(), timer.ElapsedMilliseconds, timer.ElapsedTicks); } static void Main(string[] args) { var stringList = new List() { "123123123213", "1232113213213", "123213123" }; string outcome = String.Empty; Performance(() => { outcome = string.Join(",", stringList); }); Console.WriteLine(outcome); Performance(() => { StringBuilder builder = new StringBuilder(); stringList.ForEach ( val => { builder.Append(val); builder.Append(","); } ); outcome = builder.ToString(); outcome = outcome.Substring(0, outcome.Length - 1); }); Console.WriteLine(outcome); Console.ReadKey(); } 

结果1. String.Join – 2. StringBuilder + SubString####ms (ticks)

结果

在这种情况下, String.Join更快,但如果你可以使用尾随,那么

字符串构建器

StringBuilder稍快(带尾随)。

我尝试使用StrignBuilder的这个adhoc实现比String.Join更快。 不仅仅是String.Join是一个MEMORY HOG。 当我的实现完成时,我尝试使用20000000字符串并且String.Join总是提供OutOfMemory。 在你的机器上如果你的内存少于8Gb,它甚至可以在更少的字符串上。 评论其中一个要测试的实现。 除非您使用固定的string []数组,否则这是正确的。 String.Join在那里很好。

  public static void Main(string[] Args) { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; List strings = new List() {}; for (double d = 0; d < 8000000; d++) { strings.Add(d.ToString()); } TimeSpan upTime; TimeSpan newupTime; using (var pc = new PerformanceCounter("System", "System Up Time")) { StringBuilder sb = new StringBuilder(strings.Count); int i; pc.NextValue(); //The first call returns 0, so call this twice upTime = TimeSpan.FromSeconds(pc.NextValue()); for (i = 0; i < strings.Count - 1; i++) { sb.Append(strings[i]); sb.Append(","); } sb.Append(strings[i]); newupTime = TimeSpan.FromSeconds(pc.NextValue()); sb = null; Console.WriteLine("SB " + (newupTime - upTime).TotalMilliseconds); } using (var pc = new PerformanceCounter("System", "System Up Time")) { pc.NextValue(); upTime = TimeSpan.FromSeconds(pc.NextValue()); string s = string.Join(",", strings); newupTime = TimeSpan.FromSeconds(pc.NextValue()); Console.WriteLine("JOIN " + (newupTime - upTime).TotalMilliseconds); } } SB 406 JOIN 484 

如果想要冷却并使用重燃料运行使用聚合物

 List stringList = new List { "1234567890", "34343434", "4343434" }; Console.WriteLine( stringList.Aggregate( ( current, next ) => string.Format( "{0}, {1}", current, next ) ) ); // Outputs: 1234567890, 34343434, 4343434