StringBuilder
Строка String неизменяема: каждая склейка через + создаёт новый объект. Когда текст собирают из сотен кусочков, это расточительно. Класс StringBuilder хранит изменяемую строку: её можно дополнять и править на месте, а в конце получить готовую String.
append
Объект создают через new StringBuilder(). Метод append() добавляет значение в конец, а toString() возвращает итоговую строку:
void main() {
StringBuilder sb = new StringBuilder();
sb.append("Привет");
sb.append(", ");
sb.append("мир");
IO.println(sb.toString());
}Результат:
Привет, мирappend() принимает и числа, и символы, и boolean: они превращаются в текст. Начальный текст можно передать сразу при создании: new StringBuilder("Java").
Сборка в цикле
Главное применение StringBuilder — сборка строки в цикле. Объект один, и он просто растёт:
void main() {
StringBuilder line = new StringBuilder();
for (int i = 1; i <= 5; i++) {
line.append(i);
if (i < 5) {
line.append(" -> ");
}
}
IO.println(line);
}Результат:
1 -> 2 -> 3 -> 4 -> 5IO.println() сам вызывает toString(), поэтому объект можно передать напрямую.
Цепочки вызовов
append() и большинство других методов возвращают тот же объект StringBuilder. Поэтому вызовы можно писать цепочкой через точку:
void main() {
String receipt = new StringBuilder()
.append("Латте: $")
.append(4.5)
.append(", чашек: ")
.append(2)
.toString();
IO.println(receipt);
}Результат:
Латте: $4.5, чашек: 2Изменение содержимого
insert() вставляет значение по индексу, deleteCharAt() удаляет символ, setCharAt() заменяет его, reverse() переворачивает строку. length() работает так же, как у String:
void main() {
StringBuilder sb = new StringBuilder("Java");
sb.insert(0, "Я учу ");
IO.println(sb);
sb.deleteCharAt(sb.length() - 1);
IO.println(sb);
IO.println(new StringBuilder("потоп").reverse());
IO.println(new StringBuilder("12345").reverse());
}Результат:
Я учу Java
Я учу Jav
потоп
54321Когда нужен StringBuilder
Для склейки нескольких значений в одной строке кода + проще и не медленнее — компилятор сам оптимизирует такое выражение. StringBuilder нужен, когда строка собирается по частям в цикле или в нескольких местах программы. Внутри он держит запас памяти и расширяет его по мере роста, поэтому добавление в конец почти всегда быстрое.
Частая ошибка
StringBuilder нельзя сравнивать со строкой через equals(): у него этот метод проверяет только, один ли это объект:
void main() {
StringBuilder sb = new StringBuilder("кот");
IO.println(sb.equals("кот"));
IO.println(sb.toString().equals("кот"));
}Результат:
false
trueСначала превратите объект в строку через toString(), а потом сравнивайте.