Angesichts der 2 folgenden toString()
Implementierungen, welche bevorzugt wird:
public String toString(){
return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}
oder
public String toString(){
StringBuilder sb = new StringBuilder(100);
return sb.append("{a:").append(a)
.append(", b:").append(b)
.append(", c:").append(c)
.append("}")
.toString();
}
?
Noch wichtiger ist, dass es angesichts der nur drei Eigenschaften keinen Unterschied macht, aber an welchem Punkt würden Sie von +
concat zu wechseln StringBuilder
?
java
performance
string
concatenation
stringbuilder
kein Sequitor
quelle
quelle
StringBuilder
wie viel Größe im Voraus zugewiesen werden soll. Andernfalls muss die Größe verdoppelt werden, wenn der Speicherplatz knapp wird neueschar[]
Array kopieren dann Daten über - was teuer ist. Sie können betrügen, indem Sie die Größe angeben. Dann ist diese Array-Erstellung nicht erforderlich. Wenn Sie also glauben, dass Ihre Zeichenfolge ~ 100 Zeichen lang ist, können Sie den StringBuilder auf diese Größe einstellen und er muss intern nie erweitert werden.Antworten:
Version 1 ist vorzuziehen, da sie kürzer ist und der Compiler sie tatsächlich in Version 2 umwandelt - ohne Leistungsunterschied.
An dem Punkt, an dem Sie in einer Schleife verketten - normalerweise kann der Compiler dies nicht ersetzen
StringBuilder
.quelle
To increase the performance of repeated string concatenation, a Java compiler _may_ use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
Das Schlüsselwort, das es gibt, kann sein . Sollten wir uns nicht schützen, da dies offiziell optional ist (obwohl dies höchstwahrscheinlich implementiert ist)?Der Schlüssel ist, ob Sie eine einzelne Verkettung an einem Ort schreiben oder im Laufe der Zeit akkumulieren.
In dem von Ihnen angegebenen Beispiel macht es keinen Sinn, StringBuilder explizit zu verwenden. (Sehen Sie sich den kompilierten Code für Ihren ersten Fall an.)
Wenn Sie jedoch einen String erstellen, z. B. innerhalb einer Schleife, verwenden Sie StringBuilder.
Um dies zu verdeutlichen, gehen Sie davon aus, dass riesiges Array Tausende von Zeichenfolgen enthält: Code wie folgt:
ist sehr zeit- und speicherverschwendend im Vergleich zu:
quelle
result += s;
(im ersten Beispiel)"{a:"+ a + ", b:" + b + ", c: " + c +"}";
Ich bevorzuge:
... weil es kurz und lesbar ist.
Ich würde dies nicht für die Geschwindigkeit optimieren, wenn Sie es nicht in einer Schleife mit einer sehr hohen Wiederholungszahl verwenden und den Leistungsunterschied gemessen haben.
Ich bin damit einverstanden, dass dieses Formular verwirrend werden kann, wenn Sie viele Parameter ausgeben müssen (wie in einem der Kommentare angegeben). In diesem Fall würde ich zu einer besser lesbaren Form wechseln (möglicherweise mit ToStringBuilder von Apache-Commons - entnommen aus der Antwort von matt b) und die Leistung erneut ignorieren.
quelle
null
In den meisten Fällen sehen Sie keinen tatsächlichen Unterschied zwischen den beiden Ansätzen, aber es ist einfach, ein Worst-Case-Szenario wie dieses zu erstellen:
Die Ausgabe ist:
Das Problem ist, dass das Anhängen von + = an eine Zeichenfolge eine neue Zeichenfolge rekonstruiert, sodass etwas kostet, das linear zur Länge Ihrer Zeichenfolgen ist (Summe aus beiden).
Also - zu Ihrer Frage:
Der zweite Ansatz wäre schneller, aber weniger lesbar und schwieriger zu warten. Wie gesagt, in Ihrem speziellen Fall würden Sie den Unterschied wahrscheinlich nicht sehen.
quelle
+=
, war das ursprüngliche Beispiel eine Folge von+
, die der Compiler in einen einzelnenstring.concat
Aufruf umwandelt . Ihre Ergebnisse gelten nicht.Ich hatte auch einen Konflikt mit meinem Chef über die Tatsache, ob Append oder + verwendet werden soll. Da sie Append verwenden (ich kann es immer noch nicht herausfinden, wie sie sagen, jedes Mal, wenn ein neues Objekt erstellt wird). Also dachte ich daran, F & E zu machen. Obwohl ich die Erklärung von Michael Borgwardt liebe, wollte ich nur eine Erklärung zeigen, wenn jemand in Zukunft wirklich etwas wissen muss.
und Demontage der oben genannten Klasse kommt als heraus
Anhand der beiden obigen Codes können Sie sehen, dass Michael Recht hat. In jedem Fall wird nur ein SB-Objekt erstellt.
quelle
Seit Java 1.5 generiert die einfache einzeilige Verkettung mit "+" und StringBuilder.append () genau den gleichen Bytecode.
Verwenden Sie aus Gründen der Lesbarkeit des Codes "+".
2 Ausnahmen:
quelle
Unter Verwendung der neuesten Version von Java (1.8) zeigt die Disassembly (
javap -c
) die vom Compiler eingeführte Optimierung.+
Auchsb.append()
wird sehr ähnlicher Code generiert. Es lohnt sich jedoch, das Verhalten zu überprüfen, wenn wir es+
in einer for-Schleife verwenden.Hinzufügen von Zeichenfolgen mit + in einer for-Schleife
Java:
ByteCode :(
for
Schleifenauszug)Hinzufügen von Zeichenfolgen mit stringbuilder.append
Java:
ByteCdoe :(
for
Schleifenauszug)Es gibt jedoch einen kleinen Unterschied . Im ersten Fall, in dem
+
verwendet wurde,StringBuilder
wird für jede Schleifeniteration eine neue erstellt, und das generierte Ergebnis wird durch Ausführen einestoString()
Aufrufs (29 bis 41) gespeichert . Sie generieren also Zwischenzeichenfolgen, die Sie bei Verwendung des+
Operators in derfor
Schleife wirklich nicht benötigen .quelle
In Java 9 sollte die Version 1 schneller sein, da sie in
invokedynamic
call konvertiert wird . Weitere Details finden Sie in JEP-280 :quelle
Aus Leistungsgründen wird von der Verwendung von
+=
(String
Verkettung) abgeraten. Der Grund dafür ist: JavaString
ist unveränderlich. Jedes Mal, wenn eine neue Verkettung durchgeführt wird, wird eine neueString
erstellt (die neue hat einen anderen Fingerabdruck als die ältere, die sich bereits im String-Pool befindet ). Das Erstellen neuer Zeichenfolgen setzt den GC unter Druck und verlangsamt das Programm: Die Objekterstellung ist teuer.Der folgende Code sollte es gleichzeitig praktischer und klarer machen.
Die Ergebnisse für einen Lauf sind unten angegeben.
Ohne Berücksichtigung der Ergebnisse für 1 Verkettung (JIT hat seine Aufgabe noch nicht erfüllt), ist selbst für 10 Verkettungen die Leistungsbeeinträchtigung relevant. Bei Tausenden von Verkettungen ist der Unterschied enorm.
Lehren aus diesem sehr schnellen Experiment (mit dem obigen Code leicht reproduzierbar): Verwenden Sie das niemals, um
+=
Zeichenfolgen miteinander zu verketten, selbst in sehr einfachen Fällen, in denen einige Verkettungen erforderlich sind (wie gesagt, das Erstellen neuer Zeichenfolgen ist ohnehin teuer und übt Druck auf die aus GC).quelle
Siehe das folgende Beispiel:
Ausgabe:
Wenn die Zeichenfolgenlänge zunimmt, nimmt auch die Verkettungszeit zu.
Hier wird das
StringBuilder
definitiv gebraucht.Wie Sie sehen,
UUID.randomUUID()+"---"
wirkt sich die Verkettung: nicht wirklich auf die Zeit aus.PS: Ich denke nicht, dass die Verwendung von StringBuilder in Java wirklich ein Duplikat davon ist.
Diese Frage spricht darüber,
toString()
welche meistens keine Verkettungen von großen Zeichenfolgen ausführt.Update 2019
Seit
java8
einiger Zeit haben sich die Dinge ein wenig geändert. Es scheint, dass jetzt (java13) die Verkettungszeit von+=
praktisch dieselbe ist wiestr.concat()
. DieStringBuilder
Verkettungszeit ist jedoch immer noch konstant . (Der ursprüngliche Beitrag oben wurde leicht bearbeitet, um eine ausführlichere Ausgabe hinzuzufügen.)Bemerkenswert
bytecode:8/java.version:13
ist, dass auch die Kombination einen guten Leistungsvorteil gegenüber hatbytecode:8/java.version:8
quelle
java13
denen jetzt abweichen. Aber ich denke, die Hauptschlussfolgerung bleibt dieselbe.Apache Commons-Lang verfügt über eine ToStringBuilder- Klasse, die sehr einfach zu verwenden ist. Es macht einen guten Job, sowohl die Append-Logik zu handhaben als auch zu formatieren, wie Ihr toString aussehen soll.
Gibt eine Ausgabe zurück, die aussieht
com.blah.YourClass@abc1321f[a=whatever, b=foo]
.Oder in einer kondensierteren Form durch Verketten:
Oder wenn Sie die Reflexion verwenden möchten, um jedes Feld der Klasse einzuschließen:
Sie können auch den Stil des ToString anpassen, wenn Sie möchten.
quelle
Machen Sie die toString-Methode so lesbar wie möglich!
Die einzige Ausnahme in meinem Buch ist, wenn Sie mir beweisen können , dass es erhebliche Ressourcen verbraucht :) (Ja, dies bedeutet Profilerstellung)
Beachten Sie auch, dass der Java 5-Compiler schnelleren Code generiert als der handgeschriebene "StringBuffer" -Ansatz, der in früheren Java-Versionen verwendet wurde. Wenn Sie "+" verwenden, sind diese und zukünftige Verbesserungen kostenlos.
quelle
Es scheint eine Debatte darüber zu geben, ob die Verwendung von StringBuilder bei aktuellen Compilern noch erforderlich ist. Also dachte ich, ich gebe meine 2 Cent Erfahrung.
Ich habe eine
JDBC
Ergebnismenge von 10.000 Datensätzen (ja, ich benötige alle in einem Stapel). Die Verwendung des Operators + dauert auf meinem Computer mit ca. 5 MinutenJava 1.8
. Die VerwendungstringBuilder.append("")
dauert für dieselbe Abfrage weniger als eine Sekunde.Der Unterschied ist also riesig. Innerhalb einer Schleife
StringBuilder
ist viel schneller.quelle
In Bezug auf die Leistung ist die Verkettung von Strings mit '+' teurer, da eine völlig neue Kopie von String erstellt werden muss, da Strings in Java unveränderlich sind. Dies spielt eine besondere Rolle, wenn die Verkettung sehr häufig ist, z. B. innerhalb einer Schleife. Folgendes ist, was meine IDEE vorschlägt, wenn ich versuche, so etwas zu tun:
Allgemeine Regeln:
Hier ist ein schöner Jon Skeet Blog zu diesem Thema.
quelle
Kann ich darauf hinweisen, dass Sie, wenn Sie eine Sammlung durchlaufen und StringBuilder verwenden möchten, möglicherweise Apache Commons Lang und StringUtils.join () (in verschiedenen Varianten) ausprobieren möchten ?
Unabhängig von der Leistung müssen Sie zum millionsten Mal StringBuilder und for-Schleifen erstellen .
quelle
Folgendes habe ich in Java8 überprüft
Verwenden von StringBuilder
quelle
Ich denke, wir sollten mit dem StringBuilder-Ansatz zum Anhängen gehen. Grund dafür ist :
Die String-Verkettung erstellt jedes Mal ein neues String-Objekt (da String ein unveränderliches Objekt ist), sodass 3 Objekte erstellt werden.
Mit dem String Builder wird nur ein Objekt erstellt [StringBuilder ist veränderbar] und der weitere String wird daran angehängt.
quelle
Für solche einfachen Saiten bevorzuge ich
In der Reihenfolge würde ich sagen, dass die bevorzugte Methode zum Erstellen eines Strings die Verwendung von StringBuilder, String # concat () und dann des überladenen Operators + ist. StringBuilder ist eine signifikante Leistungssteigerung, wenn große Zeichenfolgen bearbeitet werden, genau wie die Verwendung des Operators + eine starke Leistungsminderung darstellt (exponentiell starke Abnahme mit zunehmender Zeichenfolgengröße). Das einzige Problem bei der Verwendung von .concat () ist, dass NullPointerExceptions ausgelöst werden können.
quelle