Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Конкатенация строк в Java
Конкатенация - это операция объединения нескольких строк в одну. В Java это можно делать несколькими способами, каждый из которых имеет разные характеристики производительности.
Что такое конкатенация
Букваль это просто объединение содержимого строк в новую строку:
// Простой пример конкатенации
String firstName = "John";
String lastName = "Doe";
String fullName = firstName + " " + lastName; // "John Doe"
Это выглядит просто, но под капотом происходит много действий.
Способ 1: Оператор + (плюс)
// Самый простой и читаемый способ
String result = "Hello" + " " + "World";
System.out.println(result); // "Hello World"
// Компилятор преобразует это в StringBuilder операции
// Эквивалент:
String result = new StringBuilder()
.append("Hello")
.append(" ")
.append("World")
.toString();
Способ 2: StringBuilder (РЕКОМЕНДУЕТСЯ для циклов)
// Когда нужно объединить много строк
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("Item ");
sb.append(i);
sb.append("\n");
}
String result = sb.toString();
Способ 3: String.concat()
// Метод объединения для одной операции
String result = "Hello".concat(" ").concat("World");
// Но это создает промежуточные String объекты
Способ 4: String.join()
// Хорош когда есть коллекция элементов
List<String> words = Arrays.asList("Hello", "World", "Java");
String result = String.join(" ", words); // "Hello World Java"
// Тоже работает с массивом
String result = String.join("-", "2024", "03", "22"); // "2024-03-22"
Способ 5: String.format() или printf
// Для форматированного вывода
String name = "Alice";
int age = 30;
String result = String.format("Name: %s, Age: %d", name, age);
// "Name: Alice, Age: 30"
// Или с printf
System.out.printf("Name: %s, Age: %d%n", name, age);
Способ 6: StringJoiner
// Для конкатенации с разделителем и префиксом/суффиксом
StringJoiner joiner = new StringJoiner(", ", "[", "]");
joiner.add("Apple");
joiner.add("Banana");
joiner.add("Cherry");
String result = joiner.toString(); // "[Apple, Banana, Cherry]"
Проблема производительности
// ❌ ПЛОХО - очень неэффективно
String result = "";
for (int i = 0; i < 10000; i++) {
result = result + "Item " + i; // Создает 10000 новых String объектов!
// Это O(n^2) сложность!
}
// Почему плохо:
// Итерация 1: result = "" + "Item 0" = "Item 0" (создано 1 String)
// Итерация 2: result = "Item 0" + "Item 1" = "Item 0Item 1" (создано 2 String)
// Итерация 3: результат уже занимает 20 байт, копируется в новый String
// ...
// Итерация 10000: копируется вся строка + новый элемент
// ✅ ХОРОШО - эффективно
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append("Item ").append(i);
// O(n) сложность - каждое добавление быстрое
}
String result = sb.toString();
Разница в производительности
public class StringConcatenationBenchmark {
public static void main(String[] args) {
// Тест 1: Оператор + в цикле
long start = System.currentTimeMillis();
String result = "";
for (int i = 0; i < 10000; i++) {
result = result + i;
}
long time1 = System.currentTimeMillis() - start;
System.out.println("+ оператор: " + time1 + "ms"); // ~1000ms
// Тест 2: StringBuilder
start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
result = sb.toString();
long time2 = System.currentTimeMillis() - start;
System.out.println("StringBuilder: " + time2 + "ms"); // ~1ms
// Разница: 1000x медленнее!
System.out.println("Разница: " + (time1 / time2) + "x");
}
}
Внутреннее устройство StringBuilder
// StringBuilder хранит char[] буфер, который растет при необходимости
public final class StringBuilder extends AbstractStringBuilder {
private char[] value; // Буфер
private int count; // Текущая длина
// Когда буфер полный, он увеличивается на 50% + 2
private void ensureCapacityInternal(int minimumCapacity) {
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
value.length * 2 + 2);
}
}
public StringBuilder append(String str) {
if (str == null) {
return appendNull();
}
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
}
String конкатенация компилятором
// Компилятор оптимизирует простую конкатенацию
String result = "Hello" + " " + "World";
// Компилятор видит, что это литералы, и объединяет на этапе компиляции
// Становится:
String result = "Hello World";
// Но если есть переменные:
String name = "John";
String result = "Hello " + name + " World";
// Компилятор преобразует в StringBuilder:
String result = new StringBuilder()
.append("Hello ")
.append(name)
.append(" World")
.toString();
StringBuffer vs StringBuilder
// StringBuffer - синхронизированный (старый, медленный)
StringBuffer buffer = new StringBuffer();
buffer.append("text"); // synchronized
// StringBuilder - несинхронизированный (новый, быстрый)
StringBuilder builder = new StringBuilder();
builder.append("text"); // не synchronized
// StringBuilder ~2x быстрее, используй его в однопоточном коде
Best Practices
// 1. Для простой конкатенации - используй +
String greeting = "Hello, " + name;
// 2. В цикле - используй StringBuilder
StringBuilder sb = new StringBuilder();
for (String item : items) {
sb.append(item);
}
// 3. Для коллекций - используй String.join()
String csv = String.join(",", values);
// 4. Для форматирования - используй String.format()
String formatted = String.format("%.2f", price);
// 5. Предварительно выделяй емкость если знаешь размер
StringBuilder sb = new StringBuilder(1000); // Вместо 16 по умолчанию
// 6. Не используй StringBuffer в новом коде
// StringBuffer уже устарел
Примеры из реальной работы
// Построение SQL запроса
StringBuilder query = new StringBuilder();
query.append("SELECT * FROM users WHERE ");
for (int i = 0; i < conditions.size(); i++) {
if (i > 0) query.append(" AND ");
query.append(conditions.get(i));
}
// Построение JSON
StringBuilder json = new StringBuilder("{");
json.append("\"name\":\"").append(name).append("\",");
json.append("\"age\":").append(age);
json.append("}");
// Построение CSV файла
StringBuilder csv = new StringBuilder();
for (Record record : records) {
csv.append(record.getId()).append(",")
.append(record.getName()).append(",")
.append(record.getEmail()).append("\n");
}
Вывод
Конкатенация - это объединение строк в одну. В Java есть несколько способов:
- Оператор + - хорошо для простых случаев, компилятор оптимизирует
- StringBuilder - обязателен для циклов и многократных объединений
- String.join() - удобен для коллекций
- String.format() - для форматирования
- StringJoiner - для разделителей и префиксов
Критическое правило: НИКОГДА не конкатенируй в цикле с +, используй StringBuilder!