Nein. Es ist nicht das gleiche mit
StringBuilder
als mit"a" + "b"
.
String-Instanzen sind in Java unveränderlich.
Also, wenn Sie das tun:
%Vor%Sie erstellen jedes Mal neue Zeichenfolgen, wenn Sie verketten.
Auf der anderen Seite ist StringBuilder wie ein Puffer, der beim Hinzufügen neuer Strings wachsen kann.
%Vor%Faustregel ist (geändert dank der Kommentare, die ich bekommen habe):
Wenn Sie eine Menge verketten (d. h. innerhalb einer Schleife verketten oder ein großes XML erzeugen, das aus mehreren verketteten Variablen besteht), verwenden Sie StringBuilder. Andernfalls ist eine einfache Verkettung (mit + Operator) einfach in Ordnung.
Compiler-Optimierungen spielen auch eine große Rolle beim Kompilieren dieser Art von Code.
Hier finden Sie weitere Erläuterungen zum Thema. Und weitere StackOVerflow-Fragen zum Thema:
Wenn Sie literale Zeichenfolgen (wörtlich "foo" + "bar"
) kombinieren, führt der Compiler dies zur Kompilierungszeit durch, nicht zur Laufzeit.
Wenn Sie zwei nicht-literale Strings haben und sie mit +
verbinden, verwendet der Compiler (sowieso Suns) einen StringBuilder
unter den Covern, aber nicht unbedingt auf die effizienteste Weise. Also zum Beispiel, wenn du folgendes hast:
... was der Sun-Compiler tatsächlich als Bytecode erzeugt, sieht etwas so aus:
%Vor% (Ja, wirklich - siehe Disassemblierung am Ende dieser Antwort.) Beachten Sie, dass bei jeder Iteration eine neue StringBuilder
erstellt und das Ergebnis in String
konvertiert wurde. Dies ist ineffizient (aber es spielt keine Rolle, es sei denn, Sie tun es ein viel ) wegen all der temporären Speicherzuweisungen: Es reserviert ein StringBuilder
und seinen Puffer, möglicherweise den Puffer neu zugeordnet auf dem ersten append
[wenn rv
mehr als 16 Zeichen lang ist, was die Standardpuffergröße ist] und wenn nicht auf dem ersten, dann fast sicher auf dem zweiten append
, dann weist% String
am Ende zu - Und dann macht es alles wieder bei der nächsten Iteration.
Sie könnten, wenn nötig, Effizienz gewinnen, indem Sie sie neu schreiben, um explizit ein StringBuilder
:
Dort haben wir ein explizites StringBuilder
verwendet und auch seine Anfangspufferkapazität groß genug gesetzt, um das Ergebnis zu halten. Das ist speichereffizienter, aber für unerfahrene Code-Betreuer etwas marginaler und für den Schreibvorgang etwas mühsamer. Wenn also if ein Leistungsproblem mit einer engen String Concat-Schleife auftritt, könnte dies eine Möglichkeit sein, dies zu beheben.
Sie können dieses Under-the-Cover StringBuilder
in Aktion mit der folgenden Testklasse sehen:
... das disassembliert (mit javap -c SBTest
) wie folgt:
Beachten Sie, dass eine neue StringBuilder
bei jeder Iteration der Schleife erstellt und mit der Standardpufferkapazität erstellt wird.
All diese temporären Zuteilungen klingen hässlich, aber wiederum nur, wenn Sie mit substantiellen Loops und / oder substantiellen Strings zu tun haben. Wenn der resultierende Bytecode ausgeführt wird, kann die JVM ihn auch weiter optimieren. Suns HotSpot JVM zum Beispiel ist ein sehr ausgereifter JIT-optimierender Compiler. Sobald die Schleife als Hotspot identifiziert wurde, kann sie einen Weg finden, sie zu refaktorieren. Oder natürlich nicht. : -)
Meine Faustregel ist, dass ich mir darüber Gedanken mache, wenn ich ein Leistungsproblem sehe, oder wenn ich weiß, dass ich eine Menge der Verkettung mache und es sehr wahrscheinlich ist ein Leistungsproblem sein und der Code wird vom Standpunkt der Wartbarkeit nicht wesentlich beeinträchtigt, wenn ich stattdessen StringBuilder
verwende. Der tollwütige Anti-Frühgeborenen-Optimierungs-Verband würde mir wahrscheinlich auf der zweiten Seite nicht zustimmen. : -)
Ja, es ist das gleiche, aber der Compiler kann zusätzlich die Verkettungen von Literalen optimieren, bevor der Code ausgegeben wird. "a"+"b"
kann also direkt als "ab"
ausgegeben werden.
Zum Verketten einer festen Anzahl von Strings in einem Ausdruck mit +
erzeugt der Compiler Code mit einem einzelnen StringBuilder
.
z. die Zeile
%Vor%ergibt denselben Bytecode wie die Zeile
%Vor% bei der Kompilierung mit dem Javac-Compiler. (Der Eclipse-Compiler erzeugt durch Aufruf von new StringBuilder(a)
etwas mehr optimierten Code, wodurch ein Methodenaufruf gespeichert wird.)
Wie in anderen Antworten erwähnt, verkettet der Compiler String-Literale wie "a" + "b"
in eine Zeichenkette selbst und erzeugt dabei Bytecode, der stattdessen "ab"
enthält.
Wie überall im Netz erwähnt, sollten Sie +
nicht verwenden, um eine Zeichenfolge innerhalb einer Schleife aufzubauen, weil Sie den Anfang der Zeichenfolge immer wieder in neue Zeichenfolgen kopieren. In diesem Fall sollten Sie ein StringBuilder
verwenden, das Sie außerhalb der Schleife deklarieren.
"a" + "b"
Operation
Obwohl es lesbar, leicht zu formatieren und einfach zu verstehen ist, wird das Verketten von Strings mit "+" in Java als schlecht angesehen.
Jedes Mal, wenn Sie etwas über '+' (String.concat ()) anhängen, wird ein neuer String erstellt, der alte String-Inhalt wird kopiert, der neue Inhalt wird angehängt und der alte String wird verworfen. Je größer der String, desto länger dauert es - es gibt mehr zu kopieren und mehr Müll wird produziert. Hinweis: Wenn Sie nur ein paar (zB 3,4) Strings verketten und keine Strings über eine Schleife erstellen oder nur eine Testanwendung schreiben, können Sie immer noch mit "+"
bleibenVerwenden von
StringBuilder
Bei umfangreichen Stringmanipulationen (oder beim Anhängen durch eine Schleife) wird wahrscheinlich empfohlen, "+" durch StringBuilder
.appp zu ersetzen. Die im Fall von "+" erwähnten Zwischenobjekte werden nicht während des Methodenaufrufs append()
erstellt.
Zu beachten sind auch die Optimierungen im Sun Java Compiler, der automatisch StringBuilders
( StringBuffers
& lt; 5.0) erzeugt, wenn er String-Verkettungen sieht. Aber das ist nur Sun Java Compiler.