3 回答

TA貢獻(xiàn)1871條經(jīng)驗(yàn) 獲得超13個(gè)贊
簡(jiǎn)答:這取決于。
答案很長(zhǎng):如果你已經(jīng)有一個(gè)字符串?dāng)?shù)組連在一起(用分隔符),這String.Join
是最快的方法。
String.Join
可以查看所有字符串以計(jì)算出所需的確切長(zhǎng)度,然后再次復(fù)制并復(fù)制所有數(shù)據(jù)。這意味著不會(huì)涉及額外的復(fù)制。該唯一的缺點(diǎn)是,它要經(jīng)過(guò)串的兩倍,這意味著潛在吹內(nèi)存緩存更多的時(shí)間比必要的。
如果您事先沒有將字符串作為數(shù)組,那么它的使用速度可能會(huì)更快StringBuilder
- 但是會(huì)出現(xiàn)這種情況。如果使用StringBuilder
手段做很多很多副本,那么構(gòu)建一個(gè)數(shù)組然后調(diào)用String.Join
可能會(huì)更快。
編輯:這是String.Join
對(duì)一連串調(diào)用的一次調(diào)用StringBuilder.Append
。在最初的問(wèn)題中,我們有兩個(gè)不同級(jí)別的String.Join
調(diào)用,因此每個(gè)嵌套調(diào)用都會(huì)創(chuàng)建一個(gè)中間字符串。換句話說(shuō),它更復(fù)雜,更難以猜測(cè)。我會(huì)驚訝地發(fā)現(xiàn),與典型數(shù)據(jù)相比,(在復(fù)雜性方面)要么“獲勝”。
編輯:當(dāng)我在家時(shí),我會(huì)寫一個(gè)盡可能痛苦的基準(zhǔn)StringBuilder
?;旧先绻阌幸粋€(gè)數(shù)組,其中每個(gè)元素大小是前一個(gè)元素的兩倍,并且你得到它恰到好處,你應(yīng)該能夠?yàn)槊總€(gè)附加強(qiáng)制復(fù)制(元素,而不是分隔符,盡管這需要也要考慮到)。那時(shí)它幾乎和簡(jiǎn)單的字符串連接一樣糟糕 - 但是String.Join
沒有問(wèn)題。

TA貢獻(xiàn)1906條經(jīng)驗(yàn) 獲得超10個(gè)贊
我不這么認(rèn)為。透過(guò)Reflector看,執(zhí)行效果String.Join非常優(yōu)化。它還具有預(yù)先知道要?jiǎng)?chuàng)建的字符串總大小的額外好處,因此不需要任何重新分配。
我創(chuàng)建了兩種測(cè)試方法來(lái)比較它們:
public static string TestStringJoin(double[][] array)
{
return String.Join(Environment.NewLine,
Array.ConvertAll(array,
row => String.Join(",",
Array.ConvertAll(row, x => x.ToString()))));
}
public static string TestStringBuilder(double[][] source)
{
// based on Marc Gravell's code
StringBuilder sb = new StringBuilder();
foreach (var row in source)
{
if (row.Length > 0)
{
sb.Append(row[0]);
for (int i = 1; i < row.Length; i++)
{
sb.Append(',').Append(row[i]);
}
}
}
return sb.ToString();
}
我運(yùn)行了每個(gè)方法50次,傳入一個(gè)大小的數(shù)組[2048][64]。我為兩個(gè)陣列做了這個(gè); 一個(gè)填充零,另一個(gè)填充隨機(jī)值。我在我的機(jī)器上得到了以下結(jié)果(P4 3.0 GHz,單核,無(wú)HT,從CMD運(yùn)行釋放模式):
// with zeros:
TestStringJoin took 00:00:02.2755280
TestStringBuilder took 00:00:02.3536041
// with random values:
TestStringJoin took 00:00:05.6412147
TestStringBuilder took 00:00:05.8394650
增加數(shù)組的大小[2048][512],同時(shí)將迭代次數(shù)減少到10得到以下結(jié)果:
// with zeros:
TestStringJoin took 00:00:03.7146628
TestStringBuilder took 00:00:03.8886978
// with random values:
TestStringJoin took 00:00:09.4991765
TestStringBuilder took 00:00:09.3033365
結(jié)果是可重復(fù)的(幾乎;由不同的隨機(jī)值引起的小波動(dòng))。顯然String.Join大部分時(shí)間都要快一點(diǎn)(雖然幅度非常?。?/p>
這是我用于測(cè)試的代碼:
const int Iterations = 50;
const int Rows = 2048;
const int Cols = 64; // 512
static void Main()
{
OptimizeForTesting(); // set process priority to RealTime
// test 1: zeros
double[][] array = new double[Rows][];
for (int i = 0; i < array.Length; ++i)
array[i] = new double[Cols];
CompareMethods(array);
// test 2: random values
Random random = new Random();
double[] template = new double[Cols];
for (int i = 0; i < template.Length; ++i)
template[i] = random.NextDouble();
for (int i = 0; i < array.Length; ++i)
array[i] = template;
CompareMethods(array);
}
static void CompareMethods(double[][] array)
{
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < Iterations; ++i)
TestStringJoin(array);
stopwatch.Stop();
Console.WriteLine("TestStringJoin took " + stopwatch.Elapsed);
stopwatch.Reset(); stopwatch.Start();
for (int i = 0; i < Iterations; ++i)
TestStringBuilder(array);
stopwatch.Stop();
Console.WriteLine("TestStringBuilder took " + stopwatch.Elapsed);
}
static void OptimizeForTesting()
{
Thread.CurrentThread.Priority = ThreadPriority.Highest;
Process currentProcess = Process.GetCurrentProcess();
currentProcess.PriorityClass = ProcessPriorityClass.RealTime;
if (Environment.ProcessorCount > 1) {
// use last core only
currentProcess.ProcessorAffinity
= new IntPtr(1 << (Environment.ProcessorCount - 1));
}
}
- 3 回答
- 0 關(guān)注
- 852 瀏覽
添加回答
舉報(bào)