Wie macht Java die String-Verkettung mit "+"?

8

Ich habe gelesen, wie Java mit += operator arbeitet, indem es StringBuilder verwendet.
Ist das bei einer Operation ("a" + "b") gleich?

    
Tom Brito 27.04.2010, 14:23
quelle

6 Antworten

13
  

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:

Eins , zwei , Drei .

    
Pablo Santa Cruz 27.04.2010, 14:25
quelle
34

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:

%Vor%

... 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 :

zu verwenden %Vor%

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:

%Vor%

... das disassembliert (mit javap -c SBTest ) wie folgt:

%Vor%

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. : -)

    
T.J. Crowder 27.04.2010 14:31
quelle
5

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.

    
Donal Fellows 27.04.2010 14:26
quelle
3

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.

    
Christian Semrau 27.04.2010 14:47
quelle
0
  

"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 "+"

bleiben
  

Verwenden 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.

    
ring bearer 27.04.2010 14:57
quelle
-2
  

Zeichenfolgen werden häufiger verkettet    mit dem Operator +, wie in    "Hello," + " world" + "!"

Quelle

    
inkedmn 27.04.2010 14:26
quelle

Tags und Links