JavaRush/Курсы/JAVA 25 SELF/StringBuilder и StringBuffer

StringBuilder и StringBuffer

Открыта

1. Неизменяемость строки: друг или враг?

В Java класс String — неизменяемый (immutable). Это значит, что после создания строку нельзя изменить. Каждый раз, когда вы "изменяете" строку, например, добавляете к ней что-то через + или concat(), на самом деле создаётся новый объект, а старый отправляется на свалку истории (и памяти).

Пример:

String s = "Hello";
s = s + " world!";
System.out.println(s); // Hello world!

Выглядит, будто строка s изменилась, но на самом деле создалась новая строка "Hello world!", а старая "Hello" осталась в памяти до тех пор, пока её не уберёт сборщик мусора. Если таких операций много — например, в цикле, — программа начинает тормозить и использовать лишнюю память.

Представьте, что вы строите башню из кубиков, и каждый раз, когда хотите добавить новый кубик, вам приходится перестраивать всю башню заново. Не очень экономно, правда? Вот так же работает обычный String в Java при частых изменениях.

2. StringBuilder: быстрый "строитель" строк

Класс StringBuilder (пакет java.lang, импортировать не нужно) — это специальный инструмент для эффективной сборки и изменения строк. Он изменяемый (mutable): можно добавлять, удалять, вставлять символы и подстроки без создания нового объекта на каждую операцию.

Аналогия:
Если String — это бетонная плита, то StringBuilder — конструктор LEGO: добавляете и убираете детали сколько угодно, не разбирая всё заново.

Как создать StringBuilder

StringBuilder sb = new StringBuilder(); // пустой
StringBuilder sb2 = new StringBuilder("Начальное значение");

Основные методы

Метод Описание Пример использования
append(...)
Добавить в конец строку, число, символ и т.д.
sb.append("Java");
insert(index, ...)
Вставить значение в указанную позицию
sb.insert(0, "Hello ");
delete(start, end)
Удалить символы с позиции start (включ.) до end (не включ.)
sb.delete(0, 5);
replace(start, end, str)
Заменить часть строки другим содержимым
sb.replace(0, 4, "Hi");
reverse()
Развернуть строку задом наперёд
sb.reverse();
toString()
Преобразовать в обычную строку
String s = sb.toString();
setLength(newLen)
Обрезать или дополнить строку до заданной длины
sb.setLength(3);

Пример использования

StringBuilder sb = new StringBuilder();
sb.append("Привет, ");
sb.append("мир!");
System.out.println(sb); // Привет, мир!

sb.insert(7, "Java "); // вставим "Java " после "Привет, "
System.out.println(sb); // Привет, Java мир!

sb.replace(8, 12, "другой"); // заменим "Java" на "другой"
System.out.println(sb); // Привет, другой мир!

sb.reverse();
System.out.println(sb); // !рим йогурд ,тевирП

3. StringBuffer: старший брат с защитой от многопоточности

В чём разница между StringBuilder и StringBuffer?

  • StringBuilder — быстрый, но не потокобезопасный (не синхронизированный).
  • StringBuffer — медленнее, но потокобезопасный (синхронизированный).

Если ваше приложение работает в одном потоке — используйте StringBuilder (быстрее). Если несколько потоков могут менять одну и ту же строку — используйте StringBuffer.

4. Когда использовать StringBuilder вместо String?

Сценарии

  • Частые изменения строки (добавление, удаление, вставка) в цикле или при сборке больших текстов.
  • Сборка строки из массива/списка (CSV, HTML, отчёты и т.д.).
  • Парсинг и обработка текста с большим числом операций над строкой.

Пример: сборка строки из массива

Плохой способ (через String и +):

String[] names = {"Иван", "Пётр", "Мария"};
String result = "";

for (int i = 0; i < names.length; i++)
{
    result += names[i];
    if (i < names.length - 1)
    {
        result += ", ";
    }
}
System.out.println(result);

Хороший способ (через StringBuilder):

String[] names = {"Иван", "Пётр", "Мария"};
StringBuilder sb = new StringBuilder();

for (int i = 0; i < names.length; i++)
{
    sb.append(names[i]);
    if (i < names.length - 1)
    {
        sb.append(", ");
    }
}
System.out.println(sb.toString());

Разница: в первом случае на каждом шаге создаётся новая строка, во втором — мы наращиваем один объект StringBuilder.

5. Сравнение производительности: String vs StringBuilder

// Через String
long t1 = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 10000; i++)
{
    s += i + " ";
}
long t2 = System.currentTimeMillis();
System.out.println("String: " + (t2 - t1) + " мс");

// Через StringBuilder
t1 = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
    sb.append(i).append(" ");
}
s = sb.toString();
t2 = System.currentTimeMillis();
System.out.println("StringBuilder: " + (t2 - t1) + " мс");

Итог: в большинстве случаев StringBuilder работает на порядки быстрее при множественных конкатенациях.

6. Полезные нюансы

Можно ли использовать методы String?
У StringBuilder свои методы. Чтобы получить строку — вызывайте toString().

StringBuilder sb = new StringBuilder("Hello");
String s = sb.toString(); // теперь s — обычная строка

Можно ли сравнивать StringBuilder через equals?
Осторожно: sb1.equals(sb2) сравнивает ссылки, а не содержимое. Сравнивайте так:

if (sb1.toString().equals(sb2.toString()))
{
    // содержимое совпадает
}

Можно ли передать StringBuilder в System.out.println?
Да. System.out.println вызовет toString() автоматически.

Можно ли читать символы по индексу?
Да, используйте charAt(int index), как у обычной строки.

7. Типичные ошибки при работе с StringBuilder и StringBuffer

Ошибка №1: сравнивать два StringBuilder через equals или оператор ==. Эти проверки сравнивают ссылки, а не содержимое. Используйте toString() и сравнение строк.

Ошибка №2: забывать вызывать toString() там, где ожидается String (возврат из метода, логирование, передача в API).

Ошибка №3: применять StringBuilder для пары простых конкатенаций. Запись вида "Hello, " + name нормально читается и эффективна.

Ошибка №4: конкатенировать String в цикле через +. Это неэффективно по времени и памяти — используйте StringBuilder.

Ошибка №5: путать StringBuffer и StringBuilder без необходимости. Если нет совместной модификации из нескольких потоков — выбирайте StringBuilder.

Ошибка №6: бездумно обрезать содержимое StringBuilder методом setLength(). Проверяйте корректность новой длины, данные после неё будут утеряны.

1
Задача
JAVA 25 SELF,  9 уровень,  5 лекция
Недоступна
Создание и вывод StringBuilder
Создание и вывод StringBuilder
1
Задача
JAVA 25 SELF,  9 уровень,  5 лекция
Недоступна
Вставка подстроки
Вставка подстроки
1
Задача
JAVA 25 SELF,  9 уровень,  5 лекция
Недоступна
Разворот строки
Разворот строки
1
Задача
JAVA 25 SELF,  9 уровень,  5 лекция
Недоступна
Удаление и замена
Удаление и замена
Комментарии (22)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
YaPitonE
Уровень 13
19 июля, 16:50
Через intellij idea с плагином в задание в обще не видно что перед Java должен быть пробел, не мог понять, что хотят пока не посмотрел задание в браузере :D
Nikolay Karyaev
Уровень 31
13 мая, 05:18
Задача по удалению и добавлению проверяется неправильно.
Olha
Уровень 1
14 апреля, 22:55
Какой метод используется для форматирования строки с подстановкой переменных? Что имеется ввиду под подстановкой ?
KEN Software Developer
23 апреля, 15:51
Что метод использует плейсхолдеры, и ты в них подставляешь переменные.
String name = "Alice";
int age = 25;
double price = 19.99;

String result = String.format("Name: %s, Age: %d, Price: %.2f", name, age, price);
System.out.println(result);
Olha
Уровень 1
14 апреля, 22:54
С последней задачей "Удаление и замена" очень странное! Что бы сработала пришлось поменять название переменной с а на indexLove
Ilya Pozdnyakov
Уровень 13
18 февраля, 17:07
Последнее задание выбесило. sb = sb.delete(indexLove, indexLove + "люблю".length() - 1); - не принимал sb = sb.delete(indexLove - 1, indexLove + "люблю".length()); - принял Пооочему? Какая разница какой пробел удалять? Не знаю, может я тупой и чего-то не понимаю? Администрации сайта прошу обратить внимание на ошибки в заданиях.
Юрий
Уровень 25
27 февраля, 20:24
В первом случае останется 2 пробела. Поэтому не принял.
Олег Сычев Java Developer
12 февраля, 20:00
С последней задачей "Удаление и замена" пришлось помучиться)) При чем, вывод верный, а ему все что-то не нравилось.
Александр
Уровень 14
20 января, 08:39
StringBuilder sb = new StringBuilder("Я люблю Java!");

        int indexLove = sb.indexOf("люблю");

        sb.delete(indexLove, indexLove + "люблю ".length());

        int indexJava = sb.indexOf("Java");

        sb.replace(indexJava, indexJava + "Java".length(), "программирование");

        System.out.println(sb);
и фиг его знает почему не верно)
Эдик Русинов
Уровень 31
26 января, 17:31
Должно быть System.out.println(sb.toString());
Юрий
Уровень 25
27 февраля, 20:28
println вызывает автоматически метод toString.
Emil
Уровень 50
5 декабря 2025, 08:28
Если ваше приложение работает в одном потоке — используйте StringBuilder (быстрее). Если несколько потоков могут менять одну и ту же строку — используйте StringBuffer. Что собственно является потоком? вроде нигде этого не было еще
12 декабря 2025, 20:33
Про это будет на уровне 51, пока просто забей :)
KEN Software Developer
23 апреля, 15:54
Многопоточность. Когда несколько процессов будут изменять строку и при этом будут делать это синхронно, то есть в порядке очереди. Это уже что то на крутом.
Anonymous #3656771
Уровень 20
30 октября 2025, 11:19
увеличил количество итераций в 20 раз, чтобы разница была видна нагляднее. String: 15148 мс StringBuilder: 7 мс
ph0t0nchikQA Automation Engineer в Sber
18 октября 2025, 23:42
Советы компилятора в последней задаче противоречат самому себе. так принял sb.delete(sb.indexOf("люблю") - 1, sb.indexOf("Java") - 1);