Warum StringBuilder, wenn es String gibt?


82

Ich bin gerade StringBuilderzum ersten Mal darauf gestoßen und war überrascht, da Java bereits eine sehr leistungsfähige StringKlasse hat, die das Anhängen ermöglicht.

Warum eine zweite StringKlasse?

Wo kann ich mehr erfahren StringBuilder?



Ich wollte nur erwähnen, dass dies tatsächlich einmal als Interviewfrage für mich auftauchte. Sie fragten, was ich
tun

Antworten:


171

Stringerlaubt kein Anhängen. Jede Methode, die Sie für ein aufrufen, Stringerstellt ein neues Objekt und gibt es zurück. Dies liegt daran, dass Stringes unveränderlich ist - es kann seinen internen Zustand nicht ändern.

Auf der anderen Seite StringBuilderist veränderlich. Wenn Sie es aufrufen append(..), wird das interne char-Array geändert, anstatt ein neues Zeichenfolgenobjekt zu erstellen.

Somit ist es effizienter zu haben:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i ++) {
    sb.append(i);
}

anstatt str += i, was 500 neue String-Objekte erstellen würde.

Beachten Sie, dass ich im Beispiel eine Schleife verwende. Wie Helios in den Kommentaren festhält, übersetzt der Compiler Ausdrücke automatisch String d = a + b + cin etwas Ähnliches

String d = new StringBuilder(a).append(b).append(c).toString();

Beachten Sie auch, dass es StringBufferzusätzlich zu gibt StringBuilder. Der Unterschied besteht darin, dass erstere Methoden synchronisiert haben. Wenn Sie es als lokale Variable verwenden, verwenden Sie StringBuilder. Wenn es vorkommt, dass mehrere Threads darauf zugreifen können, verwenden Sie StringBuffer(das ist seltener).


24
+1. Sie können hinzufügen: "Daher sucht StrungBuilder nach Leistung" und "Java-Compiler ersetzen Ausdrücke wie A + B + C durch neuen StringBuilder (A) .append (B) .append (C) .toString (), um die Leistung bei der Objekterstellung zu vermeiden Strafen ":)
Helios

und alles Vielen Dank. Sie alle verdienen +1 (die umgehend geliefert werden :)
an00b

Super wie der Rückruf von "unveränderlichen" Objekten.
Gary Tsui

Tolle Antworten. Was ich jedoch vermisse, ist der Grund, warum der Compiler nicht einfach herausfinden kann, wann er Stringbuilder die meiste Zeit verwenden soll , auch in for-Schleifen, damit Sie nicht als Entwickler darüber nachdenken müssen. :)
Worldsayshi

Gute Antwort . Ich möchte diese Zeilen hinzufügen: String ist unveränderlich, da das Array (dh char [] -Wert), das string enthält, als final deklariert wird, aber im Fall von StringBuilder ist das Array (dh char [] -Wert), das string enthält, nicht final. Sie können Änderungen in dem Array vornehmen, das String enthält, wenn Stringbuilder
Deen John

60

Hier ist ein konkretes Beispiel dafür, warum -

int total = 50000;
String s = ""; 
for (int i = 0; i < total; i++) { s += String.valueOf(i); } 
// 4828ms

StringBuilder sb = new StringBuilder(); 
for (int i = 0; i < total; i++) { sb.append(String.valueOf(i)); } 
// 4ms

Wie Sie sehen, ist der Leistungsunterschied erheblich.


Ps. Ich habe dies auf meinem Macbook Pro Dual Core ausgeführt.
Amir Raminfar

Dies erklärt nicht warum
Steve Kuo

25
Dies erklärt, warum StringBuilder, wenn es String gibt? Dies erklärt nicht, warum StringBuilder so schnell ist. aber das ist nicht die Frage. Das ist also eine gültige Antwort.
Kerem Baydoğan

2
@krmby - Einverstanden. Zu beantworten, warum ist wirklich für eine andere Frage gedacht.
Amir Raminfar

12
Ich denke, um den Vergleich fair zu gestalten, sollten Sie die Zeit für die Durchführung eines s = sb.ToString();am Ende angeben, damit Sie zumindest in beiden Beispielen dasselbe getan haben (Ergebnis ist a string).
Scott Whitlock

19

Die String-Klasse ist unveränderlich, während StringBuilder veränderbar ist.

String s = "Hello";
s = s + "World";

Der obige Code erstellt zwei Objekte, da String unveränderlich ist

StringBuilder sb = new StringBuilder("Hello");
sb.append("World");

Der obige Code erstellt nur ein Objekt, da StringBuilder nicht unveränderlich ist.

Lektion: Wenn String mehrmals bearbeitet / aktualisiert / angehängt werden muss, ist StringBuilder im Vergleich zu String effizienter.


8

StringBuilder dient zum Erstellen von Strings. Insbesondere bauen sie auf sehr performante Weise. Die String-Klasse ist für viele Dinge gut, aber sie hat tatsächlich eine wirklich schreckliche Leistung, wenn ein neuer String aus kleineren String-Teilen zusammengesetzt wird, da jeder neue String ein völlig neuer, neu zugewiesener String ist. (Es ist unveränderlich ) StringBuilder behält dieselbe Sequenz bei und ändert sie ( veränderbar ).


5

Die StringBuilder-Klasse ist veränderbar und ermöglicht es Ihnen, im Gegensatz zu String den Inhalt des Strings zu ändern, ohne weitere String-Objekte erstellen zu müssen. Dies kann ein Leistungsgewinn sein, wenn Sie einen String stark ändern. Es gibt auch ein Gegenstück zu StringBuilder namens StringBuffer, das ebenfalls synchronisiert ist, sodass es ideal für Multithread-Umgebungen ist.

Das größte Problem mit String ist, dass jede Operation, die Sie damit ausführen, immer ein neues Objekt zurückgibt, z. B.:

String s1 = "something";
String s2 = "else";
String s3 = s1 + s2; // this is creating a new object.

4

StringBuilder ist gut, wenn Sie mit größeren Strings arbeiten. Es hilft Ihnen, die Leistung zu verbessern.

Hier ist ein Artikel , den ich hilfreich fand.

Eine schnelle Google-Suche hätte Ihnen helfen können. Jetzt haben Sie 7 verschiedene Personen eingestellt, um eine Google-Suche für Sie durchzuführen. :) :)


Machen wir hier nicht alle unbezahlte Jobs?
Chaklader Asfak Arefe

4

Um genau zu sein, ist StringBuilder, der alle Zeichenfolgen hinzufügt, O (N), während das Hinzufügen von Zeichenfolgen O (N ^ 2) ist. Bei der Überprüfung des Quellcodes wird dies intern erreicht, indem ein veränderbares Array von Zeichen beibehalten wird. StringBuilder verwendet die Array-Längen-Duplizierungstechnik, um eine ammortisierte O (N ^ 2) -Leistung zu erzielen , auf Kosten einer möglichen Verdoppelung des erforderlichen Speichers. Sie können am Ende trimToSize aufrufen, um dies zu beheben. In der Regel werden StringBuilder-Objekte jedoch nur vorübergehend verwendet. Sie können die Leistung weiter verbessern, indem Sie eine gute Startschätzung für die endgültige Zeichenfolgengröße abgeben.


3

Effizienz.

Jedes Mal, wenn Sie Zeichenfolgen verketten, wird eine neue Zeichenfolge erstellt. Beispielsweise:

String out = "a" + "b" + "c";

Dadurch wird eine neue temporäre Zeichenfolge erstellt, in die "a" und "b" kopiert werden, um "ab" zu erhalten. Dann wird eine weitere neue temporäre Zeichenfolge erstellt, in die "ab" und "c" kopiert werden, um "abc" zu erhalten. Dieses Ergebnis wird dann zugeordnet out.

Das Ergebnis ist ein Schlemiel the Painter-Algorithmus der O (n²) (quadratischen) Zeitkomplexität.

StringBuilderAuf der anderen Seite können Sie Zeichenfolgen an Ort und Stelle anhängen und die Größe der Ausgabezeichenfolge nach Bedarf ändern.


Viele JVM-Implementierungen kompilieren Ihr Beispiel in einen StringBuilder und konvertieren dann das Endergebnis in String. In einem solchen Fall wird es nicht durch wiederholte String-Zuweisungen zusammengestellt.
Scottb

1

Java hat String, StringBuffer und StringBuilder:

  • String: Es ist unveränderlich

  • StringBuffer: Es ist veränderlich und ThreadSafe

  • StringBuilder: Es ist veränderlich, aber nicht ThreadSafe, eingeführt in Java 1.5

Zeichenfolge zB:

public class T1 {

    public static void main(String[] args){

        String s = "Hello";

        for (int i=0;i<10;i++) {

            s = s+"a";
            System.out.println(s);
        }
    }
}

}}

Ausgabe: Es werden 10 verschiedene Zeichenfolgen anstelle von nur 1 Zeichenfolge erstellt.

Helloa
Helloaa
Helloaaa
Helloaaaa
Helloaaaaa
Helloaaaaaa
Helloaaaaaaa
Helloaaaaaaaa 
Helloaaaaaaaaa 
Helloaaaaaaaaaa

StringBuilder zB: Es wird nur 1 StringBuilder-Objekt erstellt.

public class T1 {

    public static void main(String[] args){

        StringBuilder s = new StringBuilder("Hello");

        for (int i=0;i<10;i++) {    
            s.append("a");
            System.out.println(s);
        }
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.