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 лекция
Недоступен
Работа со строками
Работа со строками
Комментарии (11)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Александр Уровень 10
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);
и фиг его знает почему не верно)
Emil Уровень 13
5 декабря 2025
Если ваше приложение работает в одном потоке — используйте StringBuilder (быстрее). Если несколько потоков могут менять одну и ту же строку — используйте StringBuffer. Что собственно является потоком? вроде нигде этого не было еще
12 декабря 2025
Про это будет на уровне 51, пока просто забей :)
Anonymous #3656771 Уровень 20
30 октября 2025
увеличил количество итераций в 20 раз, чтобы разница была видна нагляднее. String: 15148 мс StringBuilder: 7 мс
ph0t0nchik Уровень 66
18 октября 2025
Советы компилятора в последней задаче противоречат самому себе. так принял sb.delete(sb.indexOf("люблю") - 1, sb.indexOf("Java") - 1);
FDX Уровень 47
10 октября 2025
В последней задаче "удаление и замена" должен быть результат "Я программирование" с одним пробелом. И в моем случае валидатору не понравилось, то как я убирал второй пробел.
Андрей Уровень 27
28 сентября 2025
Зачем пихать в тест коды смайликов? Какой сакральный смысл в этой проверке? Иногда создается впечатление что часть текстов писал гпт вместе с школьницей
Kidze Уровень 21
26 октября 2025
Ты должен понимать что символы могут быть составные и при работе с ними надо учитывать что они занимают место 2х символов, некоторые методы будут некорректно работать с ними, там есть специальные методы String для кодовых точек на такой случай вроде.
Alexandervmalysh Уровень 50
20 сентября 2025
В задаче по вставке подстроки комментарий "// поэтому вставляем после запятой и пробела (+2)" некорректный и вводит в заблуждение. По условию нам неоходимо найти позицию после запятой, соответственно положение для вставки подстроки изменится и это также проверяет валидатор
Andrzej Trufanow Уровень 27
11 сентября 2025
Что-то на этом курсе валидатор более косячный :)
Серега Батенин Уровень 12
1 октября 2025
это стандартное поведение у них)))