Какая разница между String, Stringbuffer и Stringbuilder?qa-44

Основные характеристики

  1. String:

    • Неизменяемый (immutable) класс
    • Любые операции модификации создают новый объект
    • Потокобезопасен по своей природе (но это избыточно, так как объекты неизменяемы)
  2. StringBuffer:

    • Изменяемый (mutable) класс
    • Синхронизированные методы (потокобезопасный)
    • Медленнее StringBuilder из-за накладных расходов на синхронизацию
  3. StringBuilder:

    • Изменяемый (mutable) класс
    • Не синхронизирован (не потокобезопасный)
    • Быстрее StringBuffer в однопоточных сценариях

Примеры использования

// String пример
String str = "Hello";
str = str + " World"; // Создается новый объект в памяти

// StringBuffer пример
StringBuffer sBuffer = new StringBuffer("Hello");
sBuffer.append(" World"); // Модификация существующего объекта

// StringBuilder пример
StringBuilder sBuilder = new StringBuilder("Hello");
sBuilder.append(" World"); // Модификация существующего объекта

Производительность

  1. Конкатенация в цикле:
    • String: O(n²) из-за создания новых объектов
    • StringBuffer/StringBuilder: O(n)
// Плохо (с String)
String result = "";
for (int i = 0; i < 100; i++) {
    result += i; // Каждый раз создается новый объект
}

// Хорошо (с StringBuilder)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
    sb.append(i); // Модифицируется существующий объект
}

Когда что использовать

  1. String:

    • Когда строка не будет изменяться
    • Для хранения констант
    • В многопоточной среде (хотя обычно лучше использовать immutable объекты)
  2. StringBuffer:

    • Когда нужно многопоточное изменение строк
    • В устаревшем коде (до Java 5)
  3. StringBuilder:

    • В однопоточных приложениях
    • Для интенсивных операций со строками
    • В большинстве современных приложений (по умолчанию)

Память

  • String может вызывать утечки памяти при частой модификации
  • StringBuffer/StringBuilder экономнее используют память при активных изменениях

Резюмируем

  • String - для неизменяемых строк, безопасен но неэффективен при модификациях
  • StringBuffer - потокобезопасный изменяемый вариант, но медленнее
  • StringBuilder - самый быстрый вариант для однопоточных приложений
  • В 95% случаев в современных приложениях следует использовать StringBuilder
  • Все три класса реализуют CharSequence интерфейс