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

StringBuilder и StringBuffer

JAVA 25 SELF
9 уровень , 5 лекция
Открыта

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 лекция
Недоступна
Удаление и замена
Удаление и замена
1
Опрос
Работа со строками, 9 уровень, 5 лекция
Недоступен
Работа со строками
Работа со строками
Комментарии (22)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
YaPitonE Уровень 10
19 июля 2026
Через intellij idea с плагином в задание в обще не видно что перед Java должен быть пробел, не мог понять, что хотят пока не посмотрел задание в браузере :D
Nikolay Karyaev Уровень 41
13 мая 2026
Задача по удалению и добавлению проверяется неправильно.
Olha Уровень 10
14 апреля 2026
Какой метод используется для форматирования строки с подстановкой переменных? Что имеется ввиду под подстановкой ?
KEN Уровень 13
23 апреля 2026
Что метод использует плейсхолдеры, и ты в них подставляешь переменные.

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 Уровень 10
14 апреля 2026
С последней задачей "Удаление и замена" очень странное! Что бы сработала пришлось поменять название переменной с а на indexLove
Ilya Pozdnyakov Уровень 13
18 февраля 2026
Последнее задание выбесило. sb = sb.delete(indexLove, indexLove + "люблю".length() - 1); - не принимал sb = sb.delete(indexLove - 1, indexLove + "люблю".length()); - принял Пооочему? Какая разница какой пробел удалять? Не знаю, может я тупой и чего-то не понимаю? Администрации сайта прошу обратить внимание на ошибки в заданиях.
Юрий Уровень 24
27 февраля 2026
В первом случае останется 2 пробела. Поэтому не принял.
Олег Сычев Уровень 9
12 февраля 2026
С последней задачей "Удаление и замена" пришлось помучиться)) При чем, вывод верный, а ему все что-то не нравилось.
Александр Уровень 14
20 января 2026

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 января 2026
Должно быть System.out.println(sb.toString());
Юрий Уровень 24
27 февраля 2026
println вызывает автоматически метод toString.
Emil Уровень 32
5 декабря 2025
Если ваше приложение работает в одном потоке — используйте StringBuilder (быстрее). Если несколько потоков могут менять одну и ту же строку — используйте StringBuffer. Что собственно является потоком? вроде нигде этого не было еще
12 декабря 2025
Про это будет на уровне 51, пока просто забей :)
KEN Уровень 13
23 апреля 2026
Многопоточность. Когда несколько процессов будут изменять строку и при этом будут делать это синхронно, то есть в порядке очереди. Это уже что то на крутом.
Anonymous #3656771 Уровень 20
30 октября 2025
увеличил количество итераций в 20 раз, чтобы разница была видна нагляднее. String: 15148 мс StringBuilder: 7 мс
ph0t0nchik Уровень 66
18 октября 2025
Советы компилятора в последней задаче противоречат самому себе. так принял sb.delete(sb.indexOf("люблю") - 1, sb.indexOf("Java") - 1);