Angenommen, String a und b:
a += b
a = a.concat(b)
Sind sie unter der Haube dasselbe?
Hier wird concat als Referenz dekompiliert. Ich möchte auch den +
Operator dekompilieren können, um zu sehen, was das bewirkt.
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
java
string
concatenation
shsteimer
quelle
quelle
+
dekompiliert werden kann.StringBuffer
oderStringBuilder
- (Thread unsichere so schneller stattAntworten:
Nein, nicht ganz.
Erstens gibt es einen kleinen Unterschied in der Semantik. Wenn dies der Fall
a
istnull
, wird aa.concat(b)
ausgelöst,NullPointerException
abera+=b
der ursprüngliche Wert von wird so behandelt,a
als wäre er esnull
. Darüber hinausconcat()
akzeptiert die Methode nurString
Werte, während der+
Operator das Argument stillschweigend in einen String konvertiert (unter Verwendung dertoString()
Methode für Objekte). Dieconcat()
Methode ist also strenger in dem, was sie akzeptiert.Um unter die Haube zu schauen, schreiben Sie eine einfache Klasse mit
a += b;
Jetzt zerlegen mit
javap -c
(im Sun JDK enthalten). Sie sollten eine Liste sehen, die Folgendes enthält:Also
a += b
ist das Äquivalent vonDie
concat
Methode sollte schneller sein. Mit mehr StringsStringBuilder
gewinnt die Methode jedoch zumindest in Bezug auf die Leistung.Der Quellcode von
String
undStringBuilder
(und seine paketprivate Basisklasse) ist in src.zip des Sun JDK verfügbar. Sie können sehen, dass Sie ein char-Array erstellen (Größe nach Bedarf ändern) und es dann wegwerfen, wenn Sie das Finale erstellenString
. In der Praxis ist die Speicherzuweisung überraschend schnell.Update: Wie Pawel Adamski feststellt, hat sich die Leistung im neueren HotSpot geändert.
javac
produziert immer noch genau den gleichen Code, aber der Bytecode-Compiler betrügt. Einfache Tests schlagen völlig fehl, weil der gesamte Code weggeworfen wird. SummierenSystem.identityHashCode
(nichtString.hashCode
) zeigt, dass derStringBuffer
Code einen leichten Vorteil hat. Änderungen vorbehalten, wenn das nächste Update veröffentlicht wird oder wenn Sie eine andere JVM verwenden. Von @lukaseder , eine Liste der HotSpot JVM-Eigenschaften .quelle
javap -c
in einer kompilierten Klasse sehen, die ihn verwendet. (Oh, wie in der Antwort. Sie müssen nur die Bytecode-Demontage interpretieren, was nicht so schwierig sein sollte.)StringBuilder
, wenn zwei Zeichenfolgen verbunden werden. WennString
statische Methoden zum Verketten von bis zu vier Zeichenfolgen oder aller Zeichenfolgen in a enthalten sindString[]
, kann Code bis zu vier Zeichenfolgen mit zwei Objektzuordnungen (das ErgebnisString
und seine Unterstützungchar[]
, keine redundante) und eine beliebige Anzahl von Zeichenfolgen mit drei Zuordnungen anhängen ( dasString[]
, das ErgebnisString
und das Backingchar[]
, wobei nur das erste überflüssig ist). Für die VerwendungStringBuilder
sind bestenfalls vier Zuordnungen erforderlich, und jedes Zeichen muss zweimal kopiert werden.Niyaz ist richtig, aber es ist auch erwähnenswert, dass der Operator special + vom Java-Compiler in etwas effizienteres konvertiert werden kann. Java verfügt über eine StringBuilder-Klasse, die einen nicht threadsicheren, veränderbaren String darstellt. Wenn Sie eine Reihe von String-Verkettungen ausführen, konvertiert der Java-Compiler unbeaufsichtigt
in
was für große Saiten deutlich effizienter ist. Soweit ich weiß, geschieht dies nicht, wenn Sie die Concat-Methode verwenden.
Die concat-Methode ist jedoch effizienter, wenn eine leere Zeichenfolge mit einer vorhandenen Zeichenfolge verknüpft wird. In diesem Fall muss die JVM kein neues String-Objekt erstellen und kann einfach das vorhandene zurückgeben. Weitere Informationen finden Sie in der Concat-Dokumentation .
Wenn Sie also große Bedenken hinsichtlich der Effizienz haben, sollten Sie die Concat-Methode verwenden, wenn Sie möglicherweise leere Strings verketten, und andernfalls + verwenden. Der Leistungsunterschied sollte jedoch vernachlässigbar sein und Sie sollten sich wahrscheinlich nie darum kümmern.
quelle
String
- wie du sagst,concat
hat eine Ausnahme, wenn du eine leere konzentrierstString
.Ich habe einen ähnlichen Test wie @marcio durchgeführt, aber stattdessen mit der folgenden Schleife:
Nur zum guten Teil habe ich auch reingeworfen
StringBuilder.append()
. Jeder Test wurde 10 Mal ausgeführt, mit 100.000 Wiederholungen für jeden Lauf. Hier sind die Ergebnisse:StringBuilder
gewinnt zweifellos. Das Ergebnis der Uhrzeit war für die meisten Läufe 0 und die längste dauerte 16 ms.a += b
dauert ungefähr 40000 ms (40 s) für jeden Lauf.concat
erfordert nur 10000 ms (10 s) pro Lauf.Ich habe die Klasse noch nicht dekompiliert, um die Interna zu sehen oder sie durch den Profiler zu führen, aber ich vermute, dass ich
a += b
viel Zeit damit verbringe, neue Objekte zu erstellenStringBuilder
und sie dann wieder zu konvertierenString
.quelle
+
für zwei Zeichenfolgen verwendet wird, gibt es Fälle, in denen die VerwendungStringBuilder
besser ist als es wäreString.valueOf(s1).concat(s2)
? Irgendeine Idee, warum Compiler Letzteres nicht verwenden würden [oder denvalueOf
Aufruf in Fällen weglassen , in denens1
bekannt ist, dass er nicht null ist]?Die meisten Antworten stammen aus dem Jahr 2008. Es sieht so aus, als hätten sich die Dinge im Laufe der Zeit geändert. Meine neuesten Benchmarks mit JMH zeigen, dass Java 8
+
etwa doppelt so schnell ist wieconcat
.Mein Benchmark:
Ergebnisse:
quelle
String
nie eine statische Funktion zum Bilden einer Zeichenfolge durch Verketten der Elemente von a eingefügt hatString[]
. Die Verwendung+
zum Verketten von 8 Zeichenfolgen mit einer solchen Funktion würde das Konstruieren und spätere Verlassen erfordernString[8]
, aber dies wäre das einzige Objekt, das aufgegeben werdenStringBuilder
müsste , während das Verwenden einerStringBuilder
Instanz das Konstruieren und Verlassen einer Instanz und mindestens eineschar[]
Sicherungsspeichers erfordern würde .String.join()
Methoden wurden in Java 8 als schnelle Syntax-Wrapper für diejava.util.StringJoiner
Klasse hinzugefügt .+
geändert, um solche Funktionen zu nutzen?+
, um ihn zu verwenden) würde leider mehr erfordern, als die Java-Entwickler bereit sind, zu ändern.Tom beschreibt zu Recht genau, was der Operator + tut. Es erstellt eine temporäre
StringBuilder
Datei, hängt die Teile an und endet mittoString()
.Alle bisherigen Antworten ignorieren jedoch die Auswirkungen von HotSpot-Laufzeitoptimierungen. Insbesondere werden diese temporären Vorgänge als allgemeines Muster erkannt und zur Laufzeit durch effizienteren Maschinencode ersetzt.
@marcio: Sie haben einen Mikro-Benchmark erstellt . Bei modernen JVMs ist dies keine gültige Methode zum Profilieren von Code.
Der Grund, warum die Laufzeitoptimierung wichtig ist, ist, dass viele dieser Unterschiede im Code - einschließlich der Objekterstellung - nach dem Start von HotSpot völlig unterschiedlich sind. Die einzige Möglichkeit, dies sicher zu wissen, besteht darin, Ihren Code vor Ort zu profilieren .
Schließlich sind alle diese Methoden in der Tat unglaublich schnell. Dies kann ein Fall vorzeitiger Optimierung sein. Wenn Sie Code haben, der Zeichenfolgen häufig verkettet, hat der Weg zur Maximierung der Geschwindigkeit wahrscheinlich nichts mit den von Ihnen ausgewählten Operatoren und dem von Ihnen verwendeten Algorithmus zu tun!
quelle
Wie wäre es mit einfachen Tests? Verwendete den folgenden Code:
"a + b"
Version in 2500ms ausgeführt .a.concat(b)
in 1200ms ausgeführt .Mehrmals getestet. Die
concat()
Ausführung der Version dauerte durchschnittlich die Hälfte der Zeit.Dieses Ergebnis hat mich überrascht, weil die
concat()
Methode immer eine neue Zeichenfolge erstellt (sie gibt ein "new String(result)
" zurück. Es ist bekannt, dass:Warum war der Compiler nicht in der Lage, die Zeichenfolgenerstellung in "a + b" -Code zu optimieren, da er wusste, dass immer dieselbe Zeichenfolge erstellt wurde? Es könnte eine neue Zeichenfolgenerstellung vermeiden. Wenn Sie der obigen Aussage nicht glauben, testen Sie sich selbst.
quelle
Grundsätzlich gibt es zwei wichtige Unterschiede zwischen + und der
concat
Methode.Wenn Sie die concat- Methode verwenden, können Sie nur Zeichenfolgen verketten, während Sie im Fall des Operators + die Zeichenfolge auch mit einem beliebigen Datentyp verketten können.
Zum Beispiel:
In diesem Fall sollte die Ausgabe 10Hallo sein .
In diesem Fall müssen Sie zwei obligatorische Zeichenfolgen angeben.
Der zweite und Hauptunterschied zwischen + und concat ist folgender:
Fall 1: Angenommen, ich konzentriere auf diese Weise dieselben Zeichenfolgen mit dem concat- Operator
In diesem Fall beträgt die Gesamtzahl der im Pool erstellten Objekte 7 wie folgt:
Fall 2:
Jetzt werde ich die gleichen Zeichenfolgen über den Operator + zusammenfassen
Im obigen Fall beträgt die Gesamtzahl der erstellten Objekte nur 5.
Wenn wir die Zeichenfolgen über den Operator + zusammenfassen , wird eine StringBuffer-Klasse verwaltet, um dieselbe Aufgabe wie folgt auszuführen: -
Auf diese Weise werden nur fünf Objekte erstellt.
Also Leute, das sind die grundlegenden Unterschiede zwischen + und der Concat- Methode. Genießen :)
quelle
String s="I"+"am"+"good"+"boy"; String s2 = "go".concat("od"); System.out.println(s2 == s2.intern());
Drucketrue
, was bedeutet"good"
, dass sie vor dem Aufruf nicht im String-Pool warenintern()
Der Vollständigkeit halber wollte ich hinzufügen, dass die Definition des Operators '+' im JLS SE8 15.18.1 zu finden ist :
Über die Implementierung sagt das JLS Folgendes:
Nach dem "Ein Java-Compiler kann die StringBuffer-Klasse oder eine ähnliche Technik zum Reduzieren verwenden" zu urteilen, könnten verschiedene Compiler unterschiedlichen Bytecode erzeugen.
quelle
Der Operator + kann zwischen einer Zeichenfolge und einem Datentypwert für Zeichenfolge, Zeichen, Ganzzahl, Doppel oder Gleitkomma arbeiten. Der Wert wird lediglich vor der Verkettung in seine Zeichenfolgendarstellung konvertiert.
Der Concat-Operator kann nur mit und mit Strings ausgeführt werden. Es prüft die Datentypkompatibilität und gibt einen Fehler aus, wenn sie nicht übereinstimmen.
Abgesehen davon macht der von Ihnen bereitgestellte Code dasselbe.
quelle
Das glaube ich nicht.
a.concat(b)
ist in String implementiert und ich denke, die Implementierung hat sich seit frühen Java-Maschinen nicht viel geändert. Die+
Operationsimplementierung hängt von der Java-Version und dem Compiler ab. Derzeit+
wird mit implementiertStringBuffer
, um den Vorgang so schnell wie möglich zu gestalten. Vielleicht wird sich dies in Zukunft ändern. In früheren Versionen war die Java-+
Operation auf Strings viel langsamer, da sie zu Zwischenergebnissen führte.Ich denke, das
+=
wird mit implementiert+
und ähnlich optimiert.quelle
Bei Verwendung von + nimmt die Geschwindigkeit mit zunehmender Länge der Zeichenfolge ab. Bei Verwendung von concat ist die Geschwindigkeit jedoch stabiler. Die beste Option ist die Verwendung der StringBuilder-Klasse, die dafür eine stabile Geschwindigkeit aufweist.
Ich denke du kannst verstehen warum. Der beste Weg, um lange Strings zu erstellen, ist die Verwendung von StringBuilder () und append (). Beide Geschwindigkeiten sind nicht akzeptabel.
quelle