В каких случаях в Java следует использовать StringBuilder вместо конкатенации строк?

Ответ

StringBuilder следует использовать при многократной модификации строки в цикле или методе (например, построение SQL-запроса, XML/JSON). Это предотвращает создание множества промежуточных неизменяемых (immutable) объектов String и повышает производительность.

Почему это важно:

  • Класс String immutable. Операция str1 + str2 создает новый объект в куче, копируя содержимое.
  • В цикле это приводит к квадратичной сложности O(n²) по времени и памяти.
  • StringBuilder использует изменяемый внутренний буфер (массив char), что дает линейную сложность O(n).

Пример сравнения:

// НЕЭФФЕКТИВНО: создается много объектов String
String result = "";
for (String item : list) {
    result += item; // Новый String на каждой итерации
}

// ЭФФЕКТИВНО: один объект StringBuilder
StringBuilder sb = new StringBuilder();
for (String item : list) {
    sb.append(item);
}
String result = sb.toString();

Исключения (когда StringBuilder не нужен):

  • Простая конкатенация нескольких литералов: "Hello, " + name. Компилятор оптимизирует это сам.
  • Если требуется потокобезопасность — используйте StringBuffer.

Best Practice: При конкатенации более чем 3-4 строк в цикле всегда выбирайте StringBuilder.

Ответ 18+ 🔞

А, слушай, вот эта вся хуйня со строками в Java — это вообще отдельная песня, пиздец! Ну, типа, все знают, что String — он неизменяемый, да? То есть, как бы, раз создал — и всё, блядь, приехали. Хуй там что поменяешь.

Так вот, представь себе, что ты в цикле делаешь что-то типа result += item;. И думаешь: "Ну и чё такого, работает же, ёпта!". А под капотом-то, сука, происходит форменный пиздец! Каждый раз, когда ты пишешь этот плюсик, Java, такая: "О, бля! Новая строка нужна!". И создаёт новый объект, старый копирует, новый кусочек добавляет... И так на каждой итерации, блядь!

Вот смотри, если у тебя в списке, допустим, 1000 элементов, то это получается 1000 новых объектов, которые потом мусорщик будет выгребать, аж пот течёт. Сложность-то, блядь, квадратичная получается, O(n²)! Это как пытаться вычерпать озеро чайной ложкой, пока тебя самого не накрыло медным тазом от нехватки памяти.

А теперь, внимание, ёбушки-воробушки, выход есть! Это StringBuilder, сука! Он же умный, хитрая жопа. У него внутри массив символов, который он просто расширяет, когда надо. Никаких лишних копирований, всё по-взрослому, линейная сложность O(n). Красота!

// Вот так делать — это пиздопроебибна идея. Не делай так.
String result = "";
for (String item : list) {
    result += item; // На каждой итерации — новый объект String. Пиздец.
}

// А вот так — да, блядь, вот это по-нашему, по-хацкерски!
StringBuilder sb = new StringBuilder();
for (String item : list) {
    sb.append(item); // Просто тычем в буфер, и всё.
}
String result = sb.toString(); // И только в конце создаём одну строку.

Ну, а теперь про исключения, а то ты, чувак, сейчас начнёшь везде этот StringBuilder пихать, куда не надо. Если у тебя просто "Привет, " + name + "!" — расслабься, да похуй. Компилятор сам всё оптимизирует, он не дурак, иногда.

И ещё, если вдруг у тебя многопоточка и все потоки лезут в одну строку (что само по себе, конечно, волнение ебать), то нужен StringBuffer. Он потокобезопасный, но медленнее. Но это уже совсем другая история, про пидаров, которые налетели на общий ресурс.

Короче, правило простое, блядь: если ты в цикле собираешь строку из больше чем трёх-четырёх кусков — впендюривай StringBuilder и не парься. А то потом будешь сидеть и думать: "Чё это мой сервис так медленно работает?", а он, блядь, строки в цикле конкатенирует, как последний распиздяй.