it-swarm.com.de

Was ist der Unterschied zwischen String und StringBuffer in Java?

Was ist der Unterschied zwischen String und StringBuffer in Java?

Gibt es eine maximale Größe für String?

63
Praveen

String wird verwendet, um Zeichenfolgen zu ändern, die nicht geändert werden können (schreibgeschützt und unveränderlich). 

StringBuffer wird zur Darstellung von Zeichen verwendet, die geändert werden können.

In Bezug auf die Leistung ist StringBuffer schneller, wenn Verkettungen ausgeführt werden. Dies liegt daran, dass Sie bei der Verkettung einer String jedes Mal ein neues Objekt erstellen (intern), da String unveränderlich ist.

Sie können auch StringBuilder verwenden, die StringBuffer ähnlich ist, jedoch nicht synchronisiert ist. Die maximale Größe für beide ist Integer.MAX_VALUE (231 - 1 = 2.147.483.647) oder maximale Heap-Größe geteilt durch 2 (siehe Wie viele Zeichen kann ein Java-String haben? ) . Weitere Informationen hier .

75
Vivin Paliath

Ein String ist unveränderlich, d. H. Wenn es erstellt wird, kann es sich niemals ändern.

Ein StringBuffer (oder sein nicht synchronisierter Cousin StringBuilder) wird verwendet, wenn Sie Stück für Stück einen String konstruieren müssen, ohne den Performance-Aufwand des Aufbaus vieler kleiner Strings auf sich zu nehmen.

Die maximale Länge für beide ist Integer.MAX_VALUE, da sie intern als Arrays gespeichert werden und Java-Arrays nur ein int als Pseudofeld der Länge haben.

Die Leistungsverbesserung zwischen Strings und StringBuffers für Mehrfachverkettung ist ziemlich signifikant. Wenn Sie den folgenden Testcode ausführen, werden Sie den Unterschied sehen. Auf meinem alten Laptop mit Java 6 bekomme ich folgende Ergebnisse:

 Concat mit String nahm: 1781ms 
 Concat mit StringBuffer nahm: 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
Simon Nickerson
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
23
Karthik Reddy

String ist eine unveränderliche Klasse. Das heißt, sobald Sie eine Instanz einer Zeichenfolge wie folgt instanziieren:

String str1 = "hello";

Das Objekt im Speicher kann nicht geändert werden. Stattdessen müssen Sie eine neue Instanz erstellen, den alten String kopieren und wie in diesem Beispiel alles andere anhängen:

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

Was wirklich passiert ist, ist, dass wir das vorhandene str1-Objekt NICHT aktualisieren ... Wir teilen alle Speicher neu zusammen, kopieren die "Hallo" -Daten und fügen "World!" Hinzu. Setzen Sie dann die Referenz str1 so, dass sie auf diesen neuen Speicher zeigt. Unter der Haube sieht es also eher so aus:

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

Daraus folgt, dass dieser Vorgang "Kopieren + Einfügen und Bewegen im Speicher" sehr kostenintensiv sein kann, wenn er besonders rekursiv ausgeführt wird.

Verwenden Sie StringBuilder, wenn Sie in dieser Situation immer wieder Dinge tun müssen. Es ist veränderbar und kann Strings an das Ende des aktuellen anhängen, da es durch ein wachsendes Array zurückgesetzt wird (nicht 100%, wenn dies die tatsächliche Datenstruktur ist, könnte es eine Liste sein).

10
Feisty Mango

Von der API:

Eine Thread-sichere, veränderliche Folge von Zeichen. Ein String-Puffer ist wie ein String, kann aber geändert werden. Zu jedem Zeitpunkt enthält es eine bestimmte Zeichenfolge, aber Länge und Inhalt der Folge können durch bestimmte Methodenaufrufe geändert werden. 

4
posdef

Ich habe eine interessante Antwort für die Vergleichsleistung gefunden. String vs. StringBuffer von Reggie Hutcherso Source: http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html

Java bietet die Klassen StringBuffer und String, und die String-Klasse wird zum Bearbeiten von Zeichenfolgen verwendet, die nicht geändert werden können. Einfach ausgedrückt, Objekte vom Typ String sind schreibgeschützt und unveränderlich. Die StringBuffer-Klasse wird zur Darstellung von Zeichen verwendet, die geändert werden können.

Der wesentliche Leistungsunterschied zwischen diesen beiden Klassen besteht darin, dass StringBuffer bei einfachen Verkettungen schneller als String ist. In String-Manipulationscode werden Zeichenketten routinemäßig verkettet. Bei Verwendung der String-Klasse werden Verkettungen normalerweise wie folgt ausgeführt:

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

Wenn Sie StringBuffer verwenden, um dieselbe Verkettung durchzuführen, benötigen Sie Code, der wie folgt aussieht:

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

Entwickler gehen normalerweise davon aus, dass das erste Beispiel effizienter ist, da das zweite Beispiel, bei dem die Append-Methode für die Verkettung verwendet wird, teurer ist als das erste Beispiel, bei dem der Operator + zum Verketten von zwei String-Objekten verwendet wird.

Der Operator + erscheint unschuldig, aber der erzeugte Code erzeugt einige Überraschungen. Die Verwendung eines StringBuffer für die Verkettung kann tatsächlich Code erzeugen, der erheblich schneller ist als die Verwendung eines String. Um herauszufinden, warum dies der Fall ist, müssen wir den generierten Bytecode aus unseren beiden Beispielen untersuchen. Der Bytecode für das Beispiel, das String verwendet, sieht folgendermaßen aus:

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

Der Bytecode an den Stellen 0 bis 9 wird für die erste Codezeile ausgeführt, nämlich:

 String str = new String("Stanford ");

Dann wird der Bytecode an Position 10 bis 29 für die Verkettung ausgeführt:

 str += "Lost!!";

Die Dinge werden hier interessant. Der für die Verkettung generierte Bytecode erstellt ein StringBuffer-Objekt und ruft dann seine append-Methode auf: Das temporäre StringBuffer-Objekt wird an Position 10 erstellt und seine append-Methode wird an Position 23 aufgerufen. Da die String-Klasse unveränderlich ist, muss ein StringBuffer verwendet werden Verkettung.

Nachdem die Verkettung für das StringBuffer-Objekt ausgeführt wurde, muss sie wieder in einen String konvertiert werden. Dies geschieht mit dem Aufruf der toString-Methode an Position 26. Diese Methode erstellt ein neues String-Objekt aus dem temporären StringBuffer-Objekt. Die Erstellung dieses temporären StringBuffer-Objekts und die anschließende Rückkonvertierung in ein String-Objekt sind sehr teuer.

Zusammenfassend führen die beiden obigen Codezeilen zur Erstellung von drei Objekten:

  1. Ein String-Objekt an Position 0
  2. Ein StringBuffer-Objekt an Position 10
  3. Ein String-Objekt an Position 26

Betrachten wir nun den Bytecode, der für das Beispiel mit StringBuffer generiert wurde:

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

Der Bytecode an den Stellen 0 bis 9 wird für die erste Codezeile ausgeführt:

 StringBuffer str = new StringBuffer("Stanford ");

Der Bytecode an Position 10 bis 16 wird dann für die Verkettung ausgeführt:

 str.append("Lost!!");

Beachten Sie, dass dieser Code wie im ersten Beispiel die Append-Methode eines StringBuffer-Objekts aufruft. Im Gegensatz zum ersten Beispiel muss jedoch kein temporärer StringBuffer erstellt und in ein String-Objekt konvertiert werden. Dieser Code erstellt nur ein Objekt, den StringBuffer, an Position 0.

Zusammenfassend ist die StringBuffer-Verkettung wesentlich schneller als die String-Verkettung. Offensichtlich sollten StringBuffers bei dieser Art von Vorgang verwendet werden, wenn dies möglich ist. Wenn die Funktionalität der String-Klasse gewünscht wird, ziehen Sie in Betracht, einen StringBuffer für die Verkettung zu verwenden und dann eine Konvertierung in String durchzuführen.

2
NguyenDat

Ein StringBuffer wird verwendet, um einen einzelnen String aus vielen Strings zu erstellen, z. wenn Sie Teile eines Strings in einer Schleife anhängen möchten.

Sie sollten einen StringBuilder anstelle eines StringBuffer verwenden, wenn nur ein einzelner Thread auf den StringBuffer zugreift, da der StringBuilder nicht synchronisiert ist und daher schneller ist.

AFAIK Es gibt keine Obergrenze für die Stringgröße in Java als Sprache, die JVMs haben jedoch wahrscheinlich eine Obergrenze.

2
Thomas Lötzer

Durch das Drucken des Hashcodes des String/StringBuffer-Objekts nach einer beliebigen Anfügeoperation wird das String-Objekt jedes Mal mit neuen Werten intern neu erstellt, anstatt dasselbe String-Objekt zu verwenden.

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

 }

}

Ausgabe: Es gibt den Objektwert zusammen mit seinem Hashcode aus

    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
2
DeepaGanesh

Ich verstehe zwar, dass dies kein wesentlicher Differenzierungsfaktor ist, aber ich habe heute festgestellt, dass StringBuffer (und StringBuilder) einige interessante Methoden bietet, die String nicht kennt.

  • umkehren()
  • setCharAt ()
1
jaydeep

Ein String ist ein unveränderliches Zeichenarray.

Ein StringBuffer ist ein veränderliches Zeichenarray. Wird beim Mutieren häufig in String konvertiert.

Da beide ein Array sind, entspricht die maximale Größe für beide der maximalen Größe einer Ganzzahl, die 2 ^ 31-1 ist (siehe JavaDoc , auch JavaDoc für String und StringBuffer) weil das .length-Argument eines Arrays ein primitives int ist. (Siehe Arrays ).

1
Pindatjuh

Eine StringBuffer oder ihr jüngerer und schnellerer Bruder StringBuilder wird bevorzugt, wenn Sie eine ganze Reihe von String-Verkettungen im Geschmack von tun

string += newString;

oder gleichwertig

string = string + newString;

denn die obigen Konstrukte erzeugen implizit jedes Mal new string, was eine enorme Leistung und Abnahme bedeuten wird. Eine StringBuffer/StringBuilder ist unter den Hauben am besten, um mit einem dynamisch erweiterbaren List<Character> verglichen zu werden.

1
BalusC

Die Unterschiede sind

  1. Nur in String class + Operator ist überladen. Wir können zwei String-Objekte mithilfe des Operators + zusammenstellen, im Fall von StringBuffer können wir jedoch nicht.
  2. String class überschreibt toString (), equals (), hashCode () von Object class, aber StringBuffer überschreibt nur 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 ist sowohl serializable als auch Comparable , aber StringBuffer ist nur Serializable .

    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. Wir können ein String-Objekt mit und ohne new operator erstellen, das StringBuffer-Objekt kann jedoch nur mit new operator erstellt werden.

  5. String ist unveränderlich, aber StringBuffer ist veränderbar.
  6. StringBuffer ist synchronisiert, String dagegen nicht.
  7. StringBuffer hat eine eingebaute reverse () Methode, aber String hat es nicht.
1
Arun Sudhakaran

String ist unveränderlich, das heißt, wenn Sie einen Vorgang an einem String ausführen, erstellen Sie wirklich einen neuen String.

StringBuffer ist mutierbar, und Sie können an es anhängen sowie seine Länge auf 0 zurücksetzen.

In der Praxis scheint der Compiler während der String-Verkettung aus Leistungsgründen StringBuffer zu verwenden.

1
Matthew Willis
String is immutable. 

Warum? Überprüfen Sie hier .

StringBuffer is not. It is thread safe. 

Weitere Fragen wie, wann welche und andere Konzepte verwendet werden, können nach this ermittelt werden.

Hoffe das hilft.

1
roger_that

Performance wise StringBuffer ist viel besser als String; Jedes Mal, wenn Sie die Verkettung auf String-Objekte anwenden, werden bei jeder Verkettung neue String-Objekte erstellt.

Prinzipregel: String sind unveränderlich (nicht modifizierbar) und StringBuffer sind veränderbar (modifizierbar) 

Hier ist das programmatische Experiment, bei dem Sie den Leistungsunterschied feststellen 

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

Ausgabe von String in meinem Rechner 14800

Ausgabe von StringBuffer in meinem Rechner 14