Вопрос

В чем разница между String и StringBuffer в Java?

Существует ли максимальный размер строки?

Это было полезно?

Решение

String используется для управления строками символов, которые нельзя изменить (только для чтения и неизменяемые).

StringBuffer используется для обозначения символов, которые можно изменить.

С точки зрения производительности, StringBuffer быстрее при выполнении конкатенации.Это происходит потому, что когда вы объединяете String, вы создаете новый объект (внутренне) каждый раз, поскольку String является неизменным.

Вы также можете использовать StringBuilder что похоже на StringBuffer за исключением того, что он не синхронизирован.Максимальный размер для любого из них составляет Integer.MAX_VALUE (231 - 1 = 2 147 483 647) или максимальный размер кучи, разделенный на 2 (см. Сколько символов может иметь строка Java?).Больше информации здесь.

Другие советы

А String является неизменяемым, т.е.когда оно создано, оно никогда не может измениться.

А StringBuffer (или его несинхронизированный родственник StringBuilder) используется, когда вам нужно составить строку по частям без затрат производительности, связанных с созданием большого количества маленьких Stringпо пути.

Максимальная длина для обоих — Integer.MAX_VALUE, поскольку они хранятся внутри как массивы, а массивы Java имеют только int для их псевдополя длины.

Улучшение производительности между Stringпесок StringBuffers для множественной конкатенации весьма значительна.Если вы запустите следующий тестовый код, вы увидите разницу.На моем древнем ноутбуке с Java 6 я получаю такие результаты:

Concat with String took: 1781ms
Concat with StringBuffer took: 0ms
public class Concat
{
    public static String concatWithString()
    {
        String t = "Cat";
        for (int i=0; i<10000; i++)
        {
            t = t + "Dog";
        }
        return t;
    }
    public static String concatWithStringBuffer()
    {
        StringBuffer sb = new StringBuffer("Cat");
        for (int i=0; i<10000; i++)
        {
            sb.append("Dog");
        }
        return sb.toString();
    }
    public static void main(String[] args)
    {
        long start = System.currentTimeMillis();
        concatWithString();
        System.out.println("Concat with String took: " + (System.currentTimeMillis() - start) + "ms");
        start = System.currentTimeMillis();
        concatWithStringBuffer();
        System.out.println("Concat with StringBuffer took: " + (System.currentTimeMillis() - start) + "ms");
    }
}
String                                          StringBuffer

Immutable                                       Mutable
String s=new String("karthik");                StringBuffer sb=new StringBuffer("karthik")
s.concat("reddy");                             sb.append("reddy");
System.out.println(s);                         System.out.println(sb);
O/P:karthik                                    O/P:karthikreddy

--->once we created a String object            ---->once we created a StringBuffer object
we can't perform any changes in the existing  we can perform any changes in the existing
object.If we are trying to perform any        object.It is nothing but mutablity of 
changes with those changes a new object       of a StrongBuffer object
will be created.It is nothing but Immutability
of a String object

Use String--->If you require immutabilty
Use StringBuffer---->If you require mutable + threadsafety
Use StringBuilder--->If you require mutable + with out threadsafety

String s=new String("karthik");
--->here 2 objects will be created one is heap and the other is in stringconstantpool(scp) and s is always pointing to heap object

String s="karthik"; 
--->In this case only one object will be created in scp and s is always pointing to that object only

String — неизменяемый класс.Это означает, что как только вы создадите экземпляр строки следующим образом:

String str1 = "hello";

Объект в памяти не может быть изменен.Вместо этого вам придется создать новый экземпляр, скопировать старую строку и добавить все остальное, как в этом примере:

String str1 = "hello";
str1 = str1 + " world!";

На самом деле происходит то, что мы НЕ обновляем существующий объект str1...Мы все вместе переживаем новую память, копируем данные «Привет» и добавляя «мир»! » К концу, затем настраивает ссылку STR1 на точку на эту новую память.Итак, под капотом это выглядит примерно так:

String str1 = "hello";
String str2 = str1 + " world!";
str1 = str2;

Отсюда следует, что этот процесс «копировать + вставить и перемещать данные в памяти» может быть очень дорогим, если выполнять его повторно, особенно рекурсивно.

Когда вы находитесь в ситуации, когда вам приходится делать что-то снова и снова, используйте StringBuilder.Он изменчив и может добавлять строки в конец текущей, потому что он возвращается в виде [растущего массива] (не 100%, если это фактическая структура данных, это может быть список).

Из API:

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

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

Вам следует использовать StringBuilder вместо StringBuffer, когда у вас есть только один поток, обращающийся к StringBuffer, поскольку StringBuilder не синхронизирован и, следовательно, быстрее.

AFAIK нет верхнего предела размера строки в Java как языке, но у JVM, вероятно, есть верхний предел.

Я нашел интересный ответ для сравнения производительности String и StringBuffer от Реджи Хатчерсо.Источник: http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html

Java предоставляет классы StringBuffer и String, а класс String используется для управления строками символов, которые нельзя изменить.Проще говоря, объекты типа String доступны только для чтения и неизменяемы.Класс StringBuffer используется для представления символов, которые можно изменить.

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

 String str = new String ("Stanford  ");
 str += "Lost!!";

Если бы вы использовали StringBuffer для выполнения той же конкатенации, вам понадобится код, который выглядит следующим образом:

 StringBuffer str = new StringBuffer ("Stanford ");
 str.append("Lost!!");

Разработчики обычно предполагают, что первый пример выше более эффективен, поскольку они считают, что второй пример, в котором для объединения используется метод добавления, является более затратным, чем первый пример, в котором для объединения двух объектов String используется оператор +.

Оператор + кажется невинным, но сгенерированный код преподносит некоторые сюрпризы.Использование StringBuffer для конкатенации фактически может создавать код, который работает значительно быстрее, чем использование String.Чтобы понять, почему это так, мы должны изучить сгенерированный байт-код из наших двух примеров.Байт-код примера с использованием String выглядит следующим образом:

0 new #7 <Class java.lang.String>
3 dup 
4 ldc #2 <String "Stanford ">
6 invokespecial #12 <Method java.lang.String(java.lang.String)>
9 astore_1
10 new #8 <Class java.lang.StringBuffer>
13 dup
14 aload_1
15 invokestatic #23 <Method java.lang.String valueOf(java.lang.Object)>
18 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
21 ldc #1 <String "Lost!!">
23 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
26 invokevirtual #22 <Method java.lang.String toString()>
29 astore_1

Байт-код в позициях от 0 до 9 выполняется для первой строки кода, а именно:

 String str = new String("Stanford ");

Затем для объединения выполняется байт-код в позициях с 10 по 29:

 str += "Lost!!";

Здесь все становится интереснее.Байт-код, сгенерированный для объединения, создает объект StringBuffer, а затем вызывает его метод добавления:временный объект StringBuffer создается в позиции 10, а его метод добавления вызывается в позиции 23.Поскольку класс String является неизменяемым, для объединения необходимо использовать StringBuffer.

После выполнения конкатенации объекта StringBuffer его необходимо преобразовать обратно в String.Это делается с помощью вызова метода toString в позиции 26.Этот метод создает новый объект String из временного объекта StringBuffer.Создание этого временного объекта StringBuffer и его последующее преобразование обратно в объект String обходятся очень дорого.

Таким образом, две строки кода выше приводят к созданию трех объектов:

  1. Объект String в позиции 0
  2. Объект StringBuffer в позиции 10.
  3. Объект String в позиции 26.

Теперь давайте посмотрим на байт-код, сгенерированный для примера с использованием StringBuffer:

0 new #8 <Class java.lang.StringBuffer>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
9 astore_1
10 aload_1 
11 ldc #1 <String "Lost!!">
13 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
16 pop

Байт-код в позициях от 0 до 9 выполняется для первой строки кода:

 StringBuffer str = new StringBuffer("Stanford ");

Затем байт-код в позициях с 10 по 16 выполняется для конкатенации:

 str.append("Lost!!");

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

В заключение, конкатенация StringBuffer выполняется значительно быстрее, чем конкатенация строк.Очевидно, что StringBuffers следует использовать в операциях этого типа, когда это возможно.Если вам нужна функциональность класса String, рассмотрите возможность использования StringBuffer для объединения, а затем выполните одно преобразование в String.

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

public class MutableImmutable {

/**
 * @param args
 */
public static void main(String[] args) {
    System.out.println("String is immutable");
    String s = "test";
    System.out.println(s+"::"+s.hashCode());
    for (int i = 0; i < 10; i++) {
        s += "tre";
        System.out.println(s+"::"+s.hashCode());
    }

    System.out.println("String Buffer is mutable");

    StringBuffer strBuf = new StringBuffer("test");
    System.out.println(strBuf+"::"+strBuf.hashCode());
    for (int i = 0; i < 10; i++) {
        strBuf.append("tre");
        System.out.println(strBuf+"::"+strBuf.hashCode());
    }

 }

}

Выход:Он печатает значение объекта вместе с его хэш-кодом.

    String is immutable
    test::3556498
    testtre::-1422435371
    testtretre::-1624680014
    testtretretre::-855723339
    testtretretretre::2071992018
    testtretretretretre::-555654763
    testtretretretretretre::-706970638
    testtretretretretretretre::1157458037
    testtretretretretretretretre::1835043090
    testtretretretretretretretretre::1425065813
    testtretretretretretretretretretre::-1615970766
    String Buffer is mutable
    test::28117098
    testtre::28117098
    testtretre::28117098
    testtretretre::28117098
    testtretretretre::28117098
    testtretretretretre::28117098
    testtretretretretretre::28117098
    testtretretretretretretre::28117098
    testtretretretretretretretre::28117098
    testtretretretretretretretretre::28117098
    testtretretretretretretretretretre::28117098

А StringBuffer или его младший и быстрый брат StringBuilder предпочтителен всякий раз, когда вы собираетесь выполнить множество конкатенаций строк в духе

string += newString;

или эквивалентно

string = string + newString;

поскольку приведенные выше конструкции неявно создают новый string каждый раз, что будет огромной производительностью и падением.А StringBuffer / StringBuilder лучше всего сравнивать с динамически расширяемым List<Character>.

А String представляет собой неизменяемый массив символов.

А StringBuffer представляет собой изменяемый массив символов.Часто конвертируется обратно в String когда закончите мутировать.

Поскольку оба являются массивами, максимальный размер обоих равен максимальному размеру целого числа, которое равно 2^31-1 (см. JavaDoc, также ознакомьтесь с JavaDoc для обоих String и StringBuffer).Это потому, что .length аргумент массива является примитивом int.(Видеть Массивы).

Строка является неизменяемой, а это означает, что когда вы выполняете операцию над строкой, вы фактически создаете совершенно новую строку.

СтрокаБуфер является изменяемым, и вы можете добавить к нему, а также сбросить его длину до 0.

На практике компилятор, похоже, использует StringBuffer во время конкатенации строк. по соображениям производительности.

String is immutable. 

Почему?Проверять здесь.

StringBuffer is not. It is thread safe. 

Дополнительные вопросы, например, когда использовать какие и другие концепции, можно выяснить после этот.

Надеюсь это поможет.

Хотя я понимаю, что это не является основным отличительным фактором, сегодня я заметил, что StringBuffer (и StringBuilder) предоставляет некоторые интересные методы, которых нет в String.

  • обеспечить регресс()
  • setCharAt()

Различия

  1. Только в Нить сорт + оператор перегружен.Мы можем объединить два объекта String, используя + оператор, но в случае СтрокаБуфер мы не можем.
  2. Нить класс переопределяет toString(), Equals(), hashCode() из Объект класс, но СтрокаБуфер переопределяет только toString().

    String s1 = new String("abc");
    String s2 = new String("abc");
    System.out.println(s1.equals(s2));  // output true
    
    StringBuffer sb1 = new StringBuffer("abc");
    StringBuffer sb2 = new StringBuffer("abc");
    System.out.println(sb1.equals(sb2));  // output false
    
  3. Нить класс оба Сериализуемый а также Сопоставимый, но СтрокаБуфер только Сериализуемый.

    Set<StringBuffer> set = new TreeSet<StringBuffer>();
    set.add(sb1);
    set.add(sb2);
    System.out.println(set);  // gives ClassCastException because there is no Comparison mechanism
    
  4. Мы можем создать объект String с и без новый оператор, но объект StringBuffer можно создать только с помощью новый оператор.

  5. String является неизменяемым, но StringBuffer является изменчивым.
  6. StringBuffer синхронизируется, а String — нет.
  7. StringBuffer имеет встроенный обеспечить регресс() метод, но у String его нет.

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

Основное правило: Строки являются неизменяемыми (неизменяемыми), а StringBuffer изменяемыми (изменяемыми).

Вот программный эксперимент, в котором вы получаете разницу в производительности

public class Test {

  public static int LOOP_ITERATION= 100000;

  public static void stringTest(){
    long startTime = System.currentTimeMillis();
    String string = "This";
    for(int i=0;i<LOOP_ITERATION;i++){
        string = string+"Yasir";
    }

    long endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);    
  }

  public static void stringBufferTest(){
    long startTime = System.currentTimeMillis();
    StringBuffer stringBuffer = new StringBuffer("This");
    for(int i=0;i<LOOP_ITERATION;i++){
        stringBuffer.append("Yasir");
    }

    long endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);
  }

  public static void main(String []args){
    stringTest()
    stringBufferTest(); 
  }
 }

Вывод строки находится на моей машине 14800

Вывод StringBuffer находится на моей машине 14

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top