Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работает StringBuilder под капотом
StringBuilder — это мутируемый класс для эффективного создания строк в Java. В отличие от String, которая неизменяема, StringBuilder внутренне модифицирует исходный массив символов.
Внутренняя структура
StringBuilder использует динамический массив символов (char[]):
public final class StringBuilder extends AbstractStringBuilder {
char[] value; // Основной буфер символов
int count; // Текущая длина содержимого
}
При создании StringBuilder резервируется буфер с начальной ёмкостью (capacity):
// Дефолтная ёмкость 16 символов
StringBuilder sb = new StringBuilder(); // capacity = 16
// С явным размером
StringBuilder sb = new StringBuilder(100); // capacity = 100
// Из существующей строки (ёмкость = длина + 16)
StringBuilder sb = new StringBuilder("Hello"); // capacity = 21
Операция append()
Когда вы вызываете append(), StringBuilder добавляет символы в массив:
public StringBuilder append(String str) {
if (str == null) {
appendNull();
} else {
int len = str.length();
ensureCapacity(count + len); // Проверка ёмкости
str.getChars(0, len, value, count);
count += len;
}
return this;
}
Динамическое расширение буфера
Когда текущее содержимое превышает ёмкость, происходит автоматическое расширение:
private void ensureCapacity(int minimumCapacity) {
if (minimumCapacity - value.length > 0) {
expandCapacity(minimumCapacity);
}
}
void expandCapacity(int minimumCapacity) {
// Новая ёмкость = (старая * 2) + 2
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0) {
newCapacity = minimumCapacity;
}
// Копируем старый буфер в новый
char[] newValue = new char[newCapacity];
System.arraycopy(value, 0, newValue, 0, count);
value = newValue;
}
Ключевой момент: каждый раз при расширении происходит копирование всего содержимого в новый массив. Это операция O(n), но она случается логарифмическое количество раз благодаря экспоненциальному росту.
Преимущество перед String
Без StringBuilder:
String result = "";
for (int i = 0; i < 1000; i++) {
result += "data";
}
С StringBuilder:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("data");
}
String result = sb.toString();
Метод toString()
public String toString() {
return new String(value, 0, count);
}
StringBuffer vs StringBuilder
StringBuffer — синхронизированная версия:
public synchronized StringBuffer append(String str) {
// потокобезопасен
}
public StringBuilder append(String str) {
// НЕ потокобезопасен, быстрее
}
Практический пример
StringBuilder sb = new StringBuilder();
System.out.println("Ёмкость: " + sb.capacity()); // 16
for (int i = 0; i < 30; i++) {
sb.append("x");
if (i == 15 || i == 17 || i == 29) {
System.out.println("После " + (i+1) + " символов, ёмкость: " + sb.capacity());
}
}
Итоги
- StringBuilder использует динамический массив char[]
- Ёмкость растёт экспоненциально (×2 + 2) при необходимости
- append() добавляет символы в O(1) амортизированной сложности
- toString() создаёт новый String
- StringBuffer — синхронизированная альтернатива
Похожие вопросы
- В чем разница между методом и конструктором класса?
- Чем занимался на проектах на которых работал?
- Используешь ли @Component над классом для определения бина
- Что такое this?
- С каким стеком работал
- Зачем нужен JVM?
- Чем занимаешься?
- Почему планируешь уходить с текущей работы?
- Каким достижением в компании гордишься?
- Что значит код 403?
- Какой REST метод используешь для удаления сущности в CRUD-приложении?
- Какие знаешь способы получить список людей по их имени в Spring Data JPA?
- Зачем код переводится в байт-код
- Почему решил развиваться в другой сфере?
- Для чего нужна аннотация Configuration в Spring?
- По какой методологии работал
- Для чего нужен внешний ключ?
- Какой базовый интерфейс для интерфейса Collection?
- Что такое Dependency Inversion?
- Зачем нужна многоформенность в Java?