Конкатенация строк и Строитель строк. Спектакль - PullRequest
26 голосов
/ 23 октября 2009

У меня есть ситуация, когда мне нужно объединить несколько строк, чтобы сформировать идентификатор класса. По сути, я просто зацикливаюсь в списке, чтобы получить значения объектов 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 займет больше времени, чем стандартная конкатенация в наиболее обычном случае.

Это лениво, элементы в списке не изменяются после создания, поэтому идентификатор вызывается лениво при вызове.

Как примечание ... Должен ли я использовать фиксированный массив вместо списка? Получу ли я улучшение производительности или памяти, если я это сделаю? (Список используется только как IEnumerable в любом случае)

Более общий взгляд на вопрос: сколько строк достаточно, чтобы прекратить конкатенацию и начать сборку?

Стоит ли мне вообще проверять сценарий?

if (myList.Count > 4) 
  ConcatWithStringBuilder(myList);

Ответы [ 10 ]

33 голосов
/ 23 октября 2009

Обычный ответ - конкатенация строк более эффективна для 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();

Ref. http://support.microsoft.com/kb/306822

14 голосов
/ 23 октября 2009

Я поддерживаю идею упрощения, пока у вас не будет веской причины сделать их сложными.

Для элементов типа 2-5 нет смысла использовать StringBuilder (если вы не повторяете эту конкатенацию непрерывно). Лучше читаемый синтаксис "+ =" имеет большее значение.

4 голосов
/ 15 сентября 2013

Почему вы не можете просто использовать

String.Concat(myList)

вместо того, чтобы изобретать велосипед? Он имеет высокую производительность и все же очень прост.
Больше информации здесь: http://msdn.microsoft.com/en-us/library/system.string.concat.aspx

4 голосов
/ 23 октября 2009

Более общий взгляд на вопрос: сколько строк достаточно, чтобы прекратить конкатенацию и начать сборку?

Это зависит от длины строк, и если вы можете предсказать целевую длину , тогда вы должны указать длину для StringBuilder конструктора , и если вы объедините их все сразу или в течение нескольких шагов.

Если вы объедините их сразу (например, s = "A" + "b" + "c" + "d") , тогда использование StringBuilder, вероятно, никогда не будет иметь смысла.

Если вы можете точно предсказать длину, то даже для 3 строк StringBuilder будет быстрее.

Обычно StringBuilder работает быстрее, если у вас более 5 конкатов. Но даже тогда простая конкатенация строк обычно имеет небольшие издержки (если только она не работает в тесном цикле).

Как только вы достигнете 10 конкатов, использование StringBuilder, скорее всего, будет благоприятным.

Редактировать: Просто чтобы прояснить: в вашем случае вы должны явно обойтись без StringBuilder.

3 голосов
/ 23 октября 2009

Объединение строк IMO более читабельно. Вы используете + и + = вместо strBldInstance.Add (), который может немного запутать код,

StringBuilder существует для того, чтобы сделать конкатенацию более производительной, гораздо большей, но я обычно жертвую чуть-чуть производительности для удобства чтения кода. На ваш код это не повлияет, если вы перебираете несколько строк здесь и там. И для этого блока кода, который часто выполняет много строк, используйте StringBuilder.

0 голосов
/ 16 января 2019

Найдена эта (производительность) тема при решении проблемы с кодом leetcode. Для строки, имеющей> 42k (или более) символов , stringBuilder по некоторым причинам быстрее.

Мой следующий код для обращения строки работал в указанном случае (> 42 тыс. Символов) с StringBuilder.

public static string ReverseString(string s)
{
   var toReturn = new StringBuilder();
   for (var i = s.Length - 1; i >= 0; i--)
   {
      toReturn.Append(s[i]);
      }
   return toReturn.ToString();
}

но та же функция не работала с конкатенацией строк, т.е. toReturn + = s [i] .

0 голосов
/ 23 октября 2009

Если вы можете, вы могли бы повеселиться и покончить с циклом for и использовать агрегат?

var concatstring = mylist.Aggregate("", (acc, item) => acc + "." + item);

не уверен в накладных расходах на это?

0 голосов
/ 23 октября 2009

Я бы использовал StringBuilder только потому, что вы хотите быть последовательными во всем приложении. Создание объекта Java / .NET также не занимает много времени, хотя я предполагаю, что при настройке для StringBuilder будет некоторая служебная работа. Не намного хуже, чем создание нескольких объектов String посредством конкатенации.

0 голосов
/ 23 октября 2009

Если вы можете оценить количество байтов, которые будут использоваться для полной строки (и использовать это для инициализации емкости StringBuilder), StringBuilder, вероятно, превзойдет класс String при выполнении более чем приблизительно 3 конкатов.

0 голосов
/ 23 октября 2009

Строитель строк, скорее всего, будет немного быстрее в этом случае, но на самом деле этого, вероятно, будет недостаточно, чтобы беспокоиться. На самом деле это будет зависеть от двух вещей: от того, сколько раз вы воссоздаете строку (потому что строки неизменны и объединение вынуждает создавать новую строку из двух существующих), и размера элементов строки, которые вы соединяются вместе Конкатенация пяти строк по 2 байта в каждой будет сильно отличаться от конкатенации 5 строк по 5000 байтов в каждой, потому что чем длиннее строка, тем больше работы должна выполнить система для выделения памяти и объектов для сбора мусора, дольше в использовании. Конструктор строк - это лучшая ставка, потому что он уже оптимизирован для объединения строк, и вам не нужно беспокоиться о соображениях производительности.

Имея все это в виду, если вы знаете, какой будет конечный размер конечной строки, построитель строк почти наверняка будет быстрее. Когда вы сообщаете ему, сколько памяти выделить для последней строки, ему не придется проходить процесс перераспределения памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...