← Назад к вопросам
Чем достигается отсутствие промежуточных объектов при использовании StringBuilder?
2.0 Middle🔥 161 комментариев
#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Отсутствие промежуточных объектов в StringBuilder
StringBuilder достигает отсутствия промежуточных объектов за счет изменяемого (mutable) внутреннего буфера. Это ключевое отличие от String, который неизменяем.
Сравнение String и StringBuilder
Проблема со String (неизменяемость)
String result = "Hello";
result = result + " World"; // Новый объект String
result = result + "!"; // Еще новый объект String
result = result + " How are you"; // И еще один новый объект
Решение с StringBuilder (изменяемость)
StringBuilder result = new StringBuilder();
result.append("Hello"); // Добавляем в буфер
result.append(" World"); // Изменяем тот же буфер
result.append("!"); // Изменяем тот же буфер
result.append(" How are you"); // Изменяем тот же буфер
String finalString = result.toString(); // Только ОДИН новый String
Внутренняя реализация StringBuilder
public class StringBuilderDemo {
public static class SimpleStringBuilder {
private char[] buffer; // Изменяемый массив
private int count; // Текущая длина
public SimpleStringBuilder() {
this.buffer = new char[16]; // Начальная емкость
this.count = 0;
}
public SimpleStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
if (count + len > buffer.length) {
expandCapacity(count + len);
}
str.getChars(0, len, buffer, count);
count += len;
return this; // Возвращаем тот же объект
}
private void expandCapacity(int minimumCapacity) {
int newCapacity = (buffer.length + 1) * 2;
if (newCapacity < minimumCapacity) {
newCapacity = minimumCapacity;
}
char[] newBuffer = new char[newCapacity];
System.arraycopy(buffer, 0, newBuffer, 0, count);
buffer = newBuffer;
}
public String toString() {
return new String(buffer, 0, count);
}
}
}
Механизм расширения буфера
public class CapacityManagement {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(); // Емкость = 16
for (int i = 0; i < 100; i++) {
sb.append("x");
// 16 → 34 → 70 → 142
}
}
}
Практическое сравнение производительности
public class PerformanceComparison {
public static void main(String[] args) {
long start = System.currentTimeMillis();
String str = "";
for (int i = 0; i < 10000; i++) {
str = str + i; // Новый String каждый раз
}
long duration1 = System.currentTimeMillis() - start;
start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
String result = sb.toString();
long duration2 = System.currentTimeMillis() - start;
System.out.println("StringBuilder быстрее в 100-1000 раз");
}
}
Ключевые отличия
String (Immutable)
- Каждая операция конкатенации создает новый объект
- Старые объекты подлежат сборке мусора
- Медленно при множественных операциях
StringBuilder (Mutable)
- Один изменяемый объект с внутренним буфером (char[])
- Все операции append() модифицируют один объект
- toString() создает только финальный String
- Очень быстро при множественных операциях
Компиляторная оптимизация
Java компилятор автоматически преобразует простую конкатенацию:
String result = "Hello" + " " + "World";
В:
String result = new StringBuilder()
.append("Hello")
.append(" ")
.append("World")
.toString();
Правило использования
Используй StringBuilder когда:
- Конкатенация происходит в циклах
- Множество операций append() подряд
- Критична производительность
Не нужен StringBuilder для:
- Одной-двух конкатенаций:
String name = first + " " + last; - Операций с неизменяемыми строками
Вывод
StringBuilder избегает промежуточных объектов через:
- Изменяемый внутренний буфер (char[])
- Переиспользование одного объекта для всех операций
- Только финальное toString() создает новый String
- Автоматическое расширение буфера без создания String объектов
Это дает огромное улучшение производительности при работе со строками, в некоторых случаях на 100-1000 раз быстрее.