Jaka jest różnica między String i StringBuffer w Javie?

Jaka jest różnica między String i StringBuffer w Javie?

Czy istnieje maksymalny rozmiar Sznurka?

Author: Jonik, 2010-03-13

15 answers

String służy do manipulowania ciągami znaków, których nie można zmienić(tylko do odczytu i niezmienne).

StringBuffer służy do reprezentowania znaków, które można modyfikować.

Pod względem wydajności, StringBuffer jest szybszy podczas wykonywania konkatenacji. Dzieje się tak dlatego, że kiedy połączysz String, tworzysz nowy obiekt (wewnętrznie) za każdym razem, gdy String jest niezmienny.

Można również użyć StringBuilder, który jest podobny do StringBuffer, z tym że nie jest zsynchronizowany. Maksymalny rozmiar dla z nich to Integer.MAX_VALUE (231 - 1 = 2,147,483,647) lub maksymalny rozmiar sterty podzielony przez 2 (Zobacz ile znaków może mieć Łańcuch Java?). Więcej informacji tutaj .

 75
Author: Vivin Paliath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:25

A String jest niezmienny, tzn. kiedy jest tworzony, nigdy nie może się zmienić.

A StringBuffer (lub jego niezsynchronizowany kuzyn StringBuilder) jest używany, gdy trzeba skonstruować ciąg kawałek po kawałku bez wydajności konstruowania wielu małych String po drodze.

Maksymalna długość dla obu jest liczbą całkowitą.MAX_VALUE, ponieważ są przechowywane wewnętrznie jako tablice, a tablice Java mają tylko int dla pseudo-pola długości.

Poprawa wydajności pomiędzy String s I StringBuffer S dla wielokrotnej konkatenacji jest dość znacząca. Jeśli uruchomisz poniższy kod testowy, zobaczysz różnicę. Na moim laptopie z Javą 6 dostaję takie wyniki:

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");
    }
}
 34
Author: Simon Nickerson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-13 17:34:28
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
 22
Author: Karthik Reddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-22 06:54:16

String jest klasą niezmienną. Oznacza to, że po utworzeniu instancji instancji ciągu znaków w ten sposób:

String str1 = "hello";

Obiekt w pamięci nie może zostać zmieniony. Zamiast tego będziesz musiał utworzyć nową instancję, skopiować Stary ciąg znaków i dołączyć cokolwiek innego, jak w tym przykładzie:

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

Tak naprawdę dzieje się to, że nie aktualizujemy istniejącego obiektu str1... razem przenosimy nową pamięć, kopiujemy dane "hello" i dodajemy " world!"do końca, wtedy ustawia odniesienie str1, aby wskazywało na tę nową pamięć. Więc to naprawdę wygląda bardziej tak pod maską:

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

Wynika z tego, że ten proces "Kopiuj + Wklej i przenoś rzeczy w pamięci" może być bardzo kosztowny, jeśli jest wykonywany powtarzalnie, szczególnie rekurencyjnie.

Kiedy jesteś w sytuacji konieczności robienia rzeczy w kółko, użyj StringBuilder. Jest zmienna i może dodawać ciągi do końca bieżącego, ponieważ jest z powrotem przez [rosnącą tablicę] (Nie 100%, jeśli jest rzeczywista struktura danych, może być lista).

 10
Author: Feisty Mango,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-04 17:48:41

From the API:

Bezpieczna dla wątku, zmienna sekwencja znaków. Bufor łańcuchów jest podobny do łańcucha, ale można go modyfikować. W dowolnym momencie zawiera określoną sekwencję znaków, ale długość i zawartość sekwencji mogą być zmieniane przez pewne wywołania metod.

 4
Author: posdef,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-04 16:50:25

StringBuffer jest używany do tworzenia pojedynczego ciągu znaków z wielu łańcuchów, np. gdy chcesz dodać części łańcucha w pętli.

Powinieneś używać Stringbuildera zamiast Stringbuffera, gdy masz tylko jeden wątek, który ma dostęp do Stringbuffera, ponieważ StringBuilder nie jest zsynchronizowany, a tym samym szybszy.

AFAIK w Javie jako języku nie ma górnego limitu dla rozmiaru napisów, ale JVMs prawdopodobnie ma górny limit.

 2
Author: Thomas Lötzer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-13 17:27:03

Znalazłem interesującą odpowiedź dla porównania Performance String vs StringBuffer Reggie Hutcherso Źródło: http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html

Java dostarcza klasy StringBuffer i String, A Klasa String jest używana do manipulowania ciągami znaków, których nie można zmienić. Mówiąc najprościej, obiekty typu String są tylko do odczytu i niezmienne. Klasa StringBuffer służy do reprezentowania znaków, które mogą być zmodyfikowany.

Znacząca różnica wydajności między tymi dwoma klasami polega na tym, że StringBuffer jest szybszy niż String podczas wykonywania prostych konkatenacji. W kodzie manipulacji ciągami znaków ciągi znaków są rutynowo łączone. Używając klasy String, konkatenacje są zazwyczaj wykonywane w następujący sposób:

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

Jeśli chcesz użyć StringBuffer do wykonania tej samej konkatenacji, potrzebujesz kodu, który wygląda tak:

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

Deweloperzy zazwyczaj zakładają, że pierwszy przykład powyżej jest bardziej wydajny, ponieważ uważają, że drugi przykład, który używa metody append do łączenia, jest bardziej kosztowny niż pierwszy przykład, który używa operatora + do łączenia dwóch obiektów łańcuchowych.

Operator + wydaje się niewinny, ale wygenerowany kod powoduje pewne niespodzianki. Używanie Stringbuffera do konkatenacji może w rzeczywistości wygenerować kod, który jest znacznie szybszy niż użycie ciągu znaków. Aby dowiedzieć się, dlaczego tak jest, musimy zbadać wygenerowany kod bajtowy z naszych dwóch przykładów. Kod bajtowy przykładu używającego ciągu znaków wygląda następująco:

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

Bajt w miejscach od 0 do 9 jest wykonywany dla pierwszej linii kodu, a mianowicie:

 String str = new String("Stanford ");

Wtedy bajt w miejscach od 10 do 29 jest wykonywany dla konkatenacji:

 str += "Lost!!";
Robi się tu ciekawie. Kod bajtowy wygenerowany dla połączenia tworzy obiekt StringBuffer, a następnie wywołuje jego metodę append: tymczasowy obiekt StringBuffer jest utworzony w lokalizacji 10, a jego metoda append jest wywoływana w lokalizacji 23. Ponieważ Klasa String jest niezmienna, do konkatenacji musi być użyty StringBuffer.

Po wykonaniu konkatenacji na obiekcie StringBuffer, musi on zostać z powrotem przekonwertowany na łańcuch znaków. Odbywa się to za pomocą wywołania metody toString w lokalizacji 26. Metoda ta wytworzy nowy obiekt String z tymczasowego obiektu StringBuffer. Tworzenie tego tymczasowego obiektu StringBuffer i jego późniejsze konwersja z powrotem do obiektu String jest bardzo kosztowna.

Podsumowując, dwie linijki powyższego kodu skutkują powstaniem trzech obiektów:

  1. obiekt typu String w miejscu 0
  2. obiekt StringBuffer w miejscu 10
  3. obiekt typu String w miejscu 26

Spójrzmy teraz na kod bajtowy wygenerowany dla przykładu przy użyciu 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

Bajtowy kod w miejscach od 0 do 9 jest wykonywany dla pierwszej linii kod:

 StringBuffer str = new StringBuffer("Stanford ");

Kod bajtowy w miejscach od 10 do 16 jest następnie wykonywany dla konkatenacji:

 str.append("Lost!!");

Zauważ, że tak jak w pierwszym przykładzie, kod ten wywołuje metodę append obiektu StringBuffer. W przeciwieństwie do pierwszego przykładu, nie ma potrzeby tworzenia tymczasowego bufora StringBuffer, a następnie przekształcania go w obiekt String. Ten kod tworzy tylko jeden obiekt, StringBuffer, w lokalizacji 0.

Podsumowując, konkatenacja Stringbuffera jest znacznie szybszy niż konkatenacja strun. Oczywiście, StringBuffers powinny być używane w tego typu operacji, gdy jest to możliwe. Jeśli pożądana jest funkcjonalność klasy String, rozważ użycie Stringbuffera do konkatenacji, a następnie wykonanie jednej konwersji na String.

 2
Author: NguyenDat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-23 06:55:49

A StringBuffer lub jego młodszy i szybszy brat StringBuilder jest preferowany, gdy masz zamiar zrobić wiele konkatenacji strun w smaku

string += newString;

Lub równoważnie

string = string + newString;

Ponieważ powyższe konstrukty domyślnie tworzą nowy ciąg za każdym razem, który będzie olbrzymią wydajnością i spadkiem. A StringBuffer / StringBuilder jest pod kapturem najlepiej porównać z dynamicznie rozszerzalnym List<Character>.

 1
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-13 17:29:49

A String jest niezmienną tablicą znaków.

A {[1] } jest zmienną tablicą znaków. Często konwertowane z powrotem do String po zakończeniu mutacji.

Ponieważ oba są tablicami, maksymalny rozmiar dla obu jest równy maksymalnemu rozmiarowi liczby całkowitej, która wynosi 2^31-1 (zobacz JavaDoc, sprawdź także JavaDoc dla obu String i StringBuffer).Jest tak, ponieważ .length argument tablicy jest prymitywnym int. (Patrz Tablice ).

 1
Author: Pindatjuh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-13 17:35:28

String jest niezmienny, co oznacza, że gdy wykonujesz operację na łańcuchu, naprawdę tworzysz cały Nowy Łańcuch.

StringBuffer jest zmienny i można do niego dołączyć, a także zresetować jego długość do 0.

W praktyce kompilator wydaje się używać StringBuffer podczas łączenia łańcuchów ze względów wydajnościowych.

 1
Author: Matthew Willis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-04 16:50:41
String is immutable. 
Dlaczego? Sprawdź TUTAJ .
StringBuffer is not. It is thread safe. 

Kolejne pytania, takie jak Kiedy używać które i inne pojęcia można rozgryźć po to .

Mam nadzieję, że to pomoże.
 1
Author: roger_that,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-25 06:44:01

Chociaż rozumiem, że nie jest to główny czynnik różnicujący, zauważyłem dzisiaj, że StringBuffer(i StringBuilder) dostarcza ciekawych metod, których String nie ma.

  • reverse ()
  • setCharAt ()
 1
Author: jaydeep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-20 03:14:56

Poprzez wydrukowanie hashcode obiektu String / StringBuffer po udowodnieniu dowolnej operacji dołączania, obiekt String jest odtwarzany wewnętrznie za każdym razem z nowymi wartościami, zamiast używać tego samego obiektu 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());
    }

 }

}

Wyjście: Wyświetla wartość obiektu wraz z jego 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
Author: DeepaGanesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-03 17:05:05

Różnice są

  1. Tylko w klasie String + operator jest przeciążony. Możemy połączyć dwa obiekty łańcuchowe za pomocą + operator, ale w przypadku StringBuffer nie możemy.
  2. String Klasa nadpisuje ToString (), equals (), hashCode () klasy obiektu, ale StringBuffer tylko nadpisuje 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. String class jest zarówno Serializowalny jak i porównywalne , ale StringBuffer jest tylko Serializowalny .

    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. Możemy utworzyć obiekt String z operatorem new i bez niego, ale obiekt StringBuffer można utworzyć tylko przy użyciu operatora new.

  5. String jest niezmienny, ale StringBuffer jest zmienny.
  6. StringBuffer jest zsynchronizowany, podczas gdy String nie jest.
  7. StringBuffer ma wbudowaną metodę reverse () , ale String nie ma jej.
 1
Author: Arun Sudhakaran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-18 05:06:43

Performance wise StringBuffer jest znacznie lepszy niż String ; ponieważ za każdym razem, gdy zastosujesz konkatenację na obiekcie String, przy każdej konkatenacji tworzony jest nowy obiekt String.

Główna zasada: String są niezmienne (niemodyfikowalne) i StringBuffer są mutowalne(modyfikowalne)

Oto eksperyment programowy, w którym uzyskujesz różnicę wydajności

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(); 
  }
 }

Wyjście String są w mojej maszynie 14800

Wyjście z StringBuffer są w mojej maszynie 14

 0
Author: Yasir Shabbir Choudhary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-11 10:21:34