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



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



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

748   15  

15 ответов:

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

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

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

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

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

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

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

повышение производительности между Strings и 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 как языке, но JVMs, вероятно, имеют верхний предел.

я нашел интересный ответ Для сравнения производительности String vs 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!!");

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

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

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, он должен быть преобразован обратно в строку. Это делается с помощью вызова метода toString на месте 26. Этот метод создает новый объект String с временный объект StringBuffer. Создание этого временного объекта StringBuffer и его последующее преобразование обратно в объект String очень дороги.

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

  1. строковый объект в точке 0
  2. объект StringBuffer в местоположении 10
  3. строковый объект в местоположении 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!!");

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

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

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

string += newString;

или

string = string + newString;

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

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

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

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

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

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

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

String is immutable. 

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

StringBuffer is not. It is thread safe. 

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

надеюсь, что это помогает.

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

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

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

различия

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

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

Performance wise StringBuffer намного лучше, чем String ; потому что всякий раз, когда вы применяете конкатенацию к объекту 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

Comments

    Ничего не найдено.