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

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

Есть ли максимальный размер для String?

Ответ 1

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

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

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

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

Ответ 2

A String неизменен, т.е. когда он создан, он никогда не может измениться.

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

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

Улучшение производительности между String и StringBuffer для множественной конкатенации весьма значимо. Если вы запустите следующий тестовый код, вы увидите разницу. На моем старинном ноутбуке с 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");
    }
}

Ответ 3

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

Ответ 4

Строка является неизменным классом. Это означает, что как только вы создадите экземпляр строки так:

String str1 = "hello";

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

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

На самом деле мы слышим, что мы не обновляем существующий объект str1... мы перераспределяем новую память, копируем "привет" данные и добавляем "мир!". до конца, затем устанавливает ссылку str1, чтобы указать на эту новую память. Так что это действительно выглядит больше под капотом:

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

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

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

Ответ 5

Из API:

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

Ответ 6

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

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

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

Ответ 7

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

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

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

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

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

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

Разработчики обычно предполагают, что первый пример выше эффективнее, потому что они считают, что второй пример, который использует метод append для конкатенации, является более дорогостоящим, чем первый пример, который использует оператор + для конкатенации двух объектов 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, затем вызывает его метод append: временный объект StringBuffer создается в местоположении 10, а его метод append вызывается в местоположении 23. Поскольку класс String неизменен, StringBuffer должен использоваться для конкатенация.

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

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

  • Объект String в местоположении 0
  • Объект StringBuffer в местоположении 10
  • Объект 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.

Ответ 8

A String - это неизменяемый массив символов.

A StringBuffer - это изменяемый массив символов. Часто преобразовывается обратно в String, когда он мутирует.

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

Ответ 9

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

string += newString;

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

string = string + newString;

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

Ответ 10

Строка неизменна, что означает, что при выполнении операции над String вы действительно создаете целую новую строку.

StringBuffer изменен, и вы можете добавить к нему, а также reset его длину до 0.

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

Ответ 11

String is immutable. 

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

StringBuffer is not. It is thread safe. 

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

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

Ответ 12

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

  • обратный()
  • setCharAt()

Ответ 13

Распечатав хэш-код объекта 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

Ответ 14

Различия

  • Только в Строке класс + оператор перегружен. Мы можем конкатрировать два объекта String с помощью оператора +, но в случае StringBuffer мы не можем. Класс
  • String переопределяет toString(), equals(), hashCode() класса Object, но StringBuffer только переопределяет 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
    
  • Класс String - Сериализуемый, а также Сопоставимый, но StringBuffer только Сериализуемый.

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

  • Строка неизменна, но StringBuffer изменен.
  • StringBuffer синхронизирован, а String - нет.
  • StringBuffer имеет встроенный метод reverse(), но String не имеет его.

Ответ 15

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

Принципиальное правило: Строка неизменяема (Non Modifiable) и 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