String

String: строковая константа, длина строки неизменяема. В Java String неизменяем.

Класс String содержит следующее определение:

/** The value is used for character storage. */
private final char value[];

/** The offset is the first index of the storage that is used. */
private final int offset;

/** The count is the number of characters in the String. */
private final int count;

Массив, используемый для хранения символов, объявлен как final, поэтому ему можно присвоить значение только один раз, и его нельзя изменить снова.

StringBuffer(JDK1.0)

StringBuffer: строковая переменная (Synchronized, т. е. потокобезопасная). Если вам нужно часто изменять содержимое строки, из соображений эффективности лучше всего использовать StringBuffer. Если вы хотите преобразовать её в тип String, можно вызвать метод toString() класса StringBuffer.

Java.lang.StringBufferПотокобезопасная изменяемая последовательность символов. В любой момент времени она содержит некоторую конкретную последовательность символов, но длину и содержимое последовательности можно изменять с помощью определённых вызовов методов. Строковые буферы можно безопасно использовать из нескольких потоков.

StringBufferОсновные операции с ним — методы append и insert, которые можно перегружать для приёма данных любого типа. Каждый метод фактически преобразует переданные данные в строку, а затем добавляет или вставляет символы этой строки в строковый буфер.

  • Метод append всегда добавляет эти символы в конец буфера;
  • метод insert добавляет символы в указанную позицию.

Например, еслиzссылается на объект строкового буфера, текущее содержимое которого —start, то этот вызов методаz.append("le")приведёт к тому, что строковый буфер будет содержатьstartle, иz.insert(4, "le")изменит строковый буфер так, что он будет содержатьstarlet 。

StringBuilder(JDK5.0)

StringBuilder: строковая переменная (не потокобезопасная). Внутри объект StringBuilder рассматривается как массив переменной длины, содержащий последовательность символов.

java.lang.StringBuilder — это изменяемая последовательность символов, впервые добавленная в JDK 5.0. Этот класс предоставляет API, совместимый с StringBuffer, но не гарантирует синхронизацию. Этот класс предназначен для использования в качестве простой замены StringBuffer, когда строковый буфер используется одним потоком (эта ситуация очень распространена).

Его конструкторы следующие:

Конструктор Описание
StringBuilder() Создаёт объект StringBuilder с ёмкостью 16 (16 пустых элементов)
StringBuilder(CharSequence cs) Создает объект StringBuilder, содержащий cs, с 16 пустыми элементами, добавленными в конец
StringBuilder(int initCapacity) Создает объект StringBuilder с емкостью initCapacity
StringBuilder(String s) Создает объект StringBuilder, содержащий s, с 16 пустыми элементами, добавленными в конец

В большинстве случаев,StringBuilder > StringBuffer. Это в основном потому, что первому не нужно учитывать потокобезопасность.

Различия между этими тремя

Основное различие в производительности между типом String и StringBuffer: String — неизменяемый объект, поэтому каждый раз, когда тип String изменяется, создается новый объект String, и затем указатель направляется на новый объект String. Следовательно, для строк, содержимое которых часто меняется, не следует использовать String, потому что создание объекта каждый раз влияет на производительность системы, особенно когда в памяти много объектов без ссылок, сборщик мусора JVM начинает работать, и производительность снижается.

При использовании класса StringBuffer операции каждый раз выполняются над самим объектом StringBuffer, а не порождают новые объекты и изменяют ссылки на объекты. Поэтому в большинстве случаев рекомендуется StringBuffer, особенно когда строковые объекты часто изменяются.

В некоторых особых случаях конкатенация строк объектов String фактически компилируется компилятором Java в конкатенацию объектов StringBuffer, поэтому в таких случаях объекты String не медленнее объектов StringBuffer, например:

String s1 = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

Скорость создания объекта String s1 не медленнее, чем у StringBuffer. В действительности в компиляторе Java автоматически выполняется следующее преобразование:

Компилятор Java напрямую компилирует первый оператор выше в:

String s1 = “This is only a simple test”;  

Таким образом, скорость очень высокая. Но следует отметить, что если объединяемые строки берутся из других объектов String, компилятор Java не преобразует их автоматически, и скорость будет не такой высокой, например:

String s2 = “This is only a”;  
String s3 = “ simple”;  
String s4 = “ test”;  
String s1 = s2 + s3 + s4;  

В этом случае компилятор Java будет действовать строго исходным способом. Операция конкатенации String (т. е. +) реализуется с помощью метода append класса StringBuilder (или StringBuffer). В этом случае для описанной выше ситуации, если s2, s3 и s4 определены как String, при конкатенации необходимо создать дополнительный StringBuffer (или StringBuilder), а затем преобразовать StringBuffer в String. Если используется StringBuffer (или StringBuilder), нет необходимости создавать дополнительный StringBuffer.

Стратегии использования

  • (1) Основной принцип: если вы хотите работать с небольшим объёмом данных, используйте String; для однопоточной работы с большими объёмами данных используйте StringBuilder; для многопоточной работы с большими объёмами данных используйте StringBuffer.

  • (2) Не используйте "+" класса String для частой конкатенации, потому что производительность крайне низкая. Следует использовать класс StringBuffer или StringBuilder. Это довольно важный принцип оптимизации Java. Например:

    String result = "";
    for (String s : hugeArray) {
        result = result + s;
    }
    
    // 使用StringBuilder
    StringBuilder sb = new StringBuilder();
    for (String s : hugeArray) {
        sb.append(s);
    }
    String result = sb.toString();
    

    Когда возникает описанная выше ситуация, очевидно, следует использовать второй способ, потому что в первом способе каждый цикл будетсоздавать результат String для сохранения результата. Помимо этого, оба способа в основном одинаковы (дляJDK 1.5 и более поздних версий)。

  • (3) Для получения лучшей производительности следует по возможности указывать их вместимость при создании StringBuffer или StringBuilder. Конечно, если длина строки, с которой вы работаете, не превышает 16 символов, указывать её не нужно. Если вместимость не указана, по умолчанию создаётся объект с вместимостью 16. Неуказание вместимости значительно снижает производительность.

  • (4) StringBuilder обычно используется внутри методов для выполнения аналогичных+функций. Поскольку он не является потокобезопасным, его можно отбросить после использования. StringBuffer в основном используется для глобальных переменных.

  • (5) При одинаковых условиях использование StringBuilder по сравнению с использованием StringBuffer позволяет достичь повышения производительности лишь примерно на 10%~15%, но это связано с риском отсутствия потокобезопасности. В реальном модульном программировании программист, отвечающий за определённый модуль, может быть не в состоянии точно определить, будет ли модуль выполняться в многопоточной среде. Поэтому: если только вы не уверены, что узким местом системы является StringBuffer, и не уверены, что ваш модуль не будет выполняться в многопоточном режиме, можете использовать StringBuilder; в противном случае по-прежнему используйте StringBuffer.

Источник статьи: https://blog.csdn.net/kingzone_2008/article/details/9220691