Gibt es einen wahrnehmbaren Unterschied zwischen der Verwendung String.format
und der Verkettung von Zeichenfolgen in Java?
Ich neige dazu zu verwenden String.format
, werde aber gelegentlich ausrutschen und eine Verkettung verwenden. Ich fragte mich, ob einer besser war als der andere.
So wie ich es sehe, haben String.format
Sie mehr Möglichkeiten, die Zeichenfolge zu "formatieren". und Verkettung bedeutet, dass Sie sich keine Sorgen machen müssen, dass Sie versehentlich zusätzliche% s eingeben oder eine verpassen.
String.format
ist auch kürzer.
Welches besser lesbar ist, hängt davon ab, wie Ihr Kopf funktioniert.
java
string
concatenation
string.format
Omar Kooheji
quelle
quelle
Antworten:
Ich würde vorschlagen, dass es besser ist, zu verwenden
String.format()
. Der Hauptgrund ist, dassString.format()
die Lokalisierung mit Text aus Ressourcendateien einfacher ist, während die Verkettung nicht lokalisiert werden kann, ohne eine neue ausführbare Datei mit unterschiedlichem Code für jede Sprache zu erstellen.Wenn Sie planen, dass Ihre App lokalisierbar ist, sollten Sie sich auch angewöhnen, Argumentpositionen für Ihre Format-Token anzugeben:
Dies kann dann lokalisiert werden und die Namen- und Zeit-Token können ausgetauscht werden, ohne dass eine Neukompilierung der ausführbaren Datei erforderlich ist, um die unterschiedliche Reihenfolge zu berücksichtigen. Mit Argumentpositionen können Sie dasselbe Argument auch wiederverwenden, ohne es zweimal an die Funktion zu übergeben:
quelle
Über die Leistung:
Die Timing-Ergebnisse sind wie folgt:
Daher ist die Verkettung viel schneller als String.format.
quelle
javap -c StringTest.class
Sie feststellen, dass der Compiler "+" nur dann automatisch in StringBuilder konvertiert, wenn Sie sich nicht in einer Schleife befinden. Wenn die Verkettung ausschließlich in einer einzelnen Zeile erfolgt, entspricht dies der Verwendung von '+'. Wenn Sie jedochmyString += "morechars";
odermyString += anotherString;
in mehreren Zeilen verwenden, werden Sie feststellen, dass möglicherweise mehr als ein StringBuilder erstellt wird. Daher ist die Verwendung von "+" nicht immer so effizient als StringBuilder.+
nicht konvertiert werden,StringBuilder.append()
sondernnew StringBuilder()
bei jeder Iteration ein passiert.Da es Diskussionen über die Leistung gibt, dachte ich, ich würde sie in einem Vergleich mit StringBuilder hinzufügen. Es ist in der Tat schneller als das concat und natürlich die Option String.format.
Um dies zu einer Art Vergleich von Äpfeln zu Äpfeln zu machen, instanziiere ich einen neuen StringBuilder in der Schleife und nicht außerhalb (dies ist tatsächlich schneller als nur eine Instanziierung, was höchstwahrscheinlich auf den Aufwand zurückzuführen ist, den Speicherplatz für das Anhängen der Schleife am Ende von neu zuzuweisen ein Baumeister).
quelle
String
. Der StringBuilder-Test benötigt, um fair zu sein, einen letzten Schritt, der den Inhalt des StringBuilder in einen String verwandelt. Sie tun dies, indem Sie anrufenbldString.toString()
. Ich hoffe das erklärt es?String s = bldString.toString();
Die Zeiten waren mit Verkettung und String fast gleichauf mit ihnen:Format = 1520 millisecond
,Concatenation = 167 millisecond
,String Builder = 173 millisecond
Ich lief sie in einer Schleife und gemittelt jeweils aus einem guten rep zu erhalten: (pre-jvm - Optimierung, eine 10000+ Schleife versuchen , wenn ich Zeit habe)Ein Problem dabei
.format
ist, dass Sie die Sicherheit des statischen Typs verlieren. Sie können zu wenige Argumente für Ihr Format haben, und Sie können die falschen Typen für die Formatspezifizierer haben - beides führt zurIllegalFormatException
Laufzeit , sodass Sie möglicherweise Protokollierungscode erhalten, der die Produktion unterbricht.Im Gegensatz dazu können die Argumente
+
vom Compiler getestet werden.Die Sicherheitsgeschichte vonprintf(nach dem die
format
Funktion modelliert ist) ist lang und erschreckend.quelle
Sie haben Ihre Antwort genau dort.
Es ist eine Frage des persönlichen Geschmacks.
Die Verkettung von Strings ist vermutlich etwas schneller, aber das sollte vernachlässigbar sein.
quelle
Hier ist ein Test mit mehreren Stichprobengrößen in Millisekunden.
}}
quelle
Hier ist der gleiche Test wie oben mit der Änderung des Aufrufs der toString () -Methode im StringBuilder . Die folgenden Ergebnisse zeigen, dass der StringBuilder-Ansatz nur etwas langsamer ist als die String-Verkettung mit dem Operator + .
Datei: StringTest.java
Shell-Befehle: (5-mal kompilieren und StringTest ausführen)
Ergebnisse :
quelle
String.format()
ist mehr als nur das Verketten von Zeichenfolgen. Beispielsweise können Sie mit Nummern in einem bestimmten Gebietsschema anzeigenString.format()
.Wenn Sie sich jedoch nicht für die Lokalisierung interessieren, gibt es keinen funktionalen Unterschied. Vielleicht ist der eine schneller als der andere, aber in den meisten Fällen wird er vernachlässigbar sein.
quelle
Im Allgemeinen sollte die Verkettung von Zeichenfolgen der Verkettung vorgezogen werden
String.format
. Letzteres hat zwei Hauptnachteile:Mit Punkt 1 meine ich, dass es nicht möglich ist zu verstehen, was ein
String.format()
Anruf in einem einzigen sequentiellen Durchgang tut. Man ist gezwungen, zwischen der Formatzeichenfolge und den Argumenten hin und her zu gehen, während man die Position der Argumente zählt. Bei kurzen Verkettungen ist dies kein großes Problem. In diesen Fällen ist die Verkettung von Zeichenfolgen jedoch weniger ausführlich.Mit Punkt 2 meine ich, dass der wichtige Teil des Erstellungsprozesses in der Formatzeichenfolge (unter Verwendung einer DSL) codiert ist . Die Verwendung von Zeichenfolgen zur Darstellung von Code hat viele Nachteile. Es ist nicht von Natur aus typsicher und erschwert das Hervorheben der Syntax, die Codeanalyse, die Optimierung usw.
Natürlich können bei der Verwendung von Tools oder Frameworks außerhalb der Java-Sprache neue Faktoren ins Spiel kommen.
quelle
Ich habe keine spezifischen Benchmarks durchgeführt, aber ich würde denken, dass die Verkettung schneller sein kann. String.format () erstellt einen neuen Formatierer, der wiederum einen neuen StringBuilder erstellt (mit einer Größe von nur 16 Zeichen). Das ist ein ziemlicher Aufwand, insbesondere wenn Sie eine längere Zeichenfolge formatieren und die Größe von StringBuilder ständig geändert werden muss.
Verkettung ist jedoch weniger nützlich und schwerer zu lesen. Wie immer lohnt es sich, einen Benchmark für Ihren Code durchzuführen, um festzustellen, welcher besser ist. Die Unterschiede können in der Server-App vernachlässigbar sein, nachdem Ihre Ressourcenpakete, Gebietsschemas usw. in den Speicher geladen wurden und der Code JITted ist.
Als bewährte Methode ist es möglicherweise eine gute Idee, einen eigenen Formatierer mit einem StringBuilder (anhängbar) und einem Gebietsschema in der richtigen Größe zu erstellen und diesen zu verwenden, wenn Sie viel zu formatieren haben.
quelle
Es könnte einen wahrnehmbaren Unterschied geben.
String.format
ist ziemlich komplex und verwendet einen regulären Ausdruck darunter. Machen Sie es sich also nicht zur Gewohnheit, ihn überall zu verwenden, sondern nur dort, wo Sie ihn brauchen.StringBuilder
wäre eine Größenordnung schneller (wie hier schon jemand betont hat).quelle
Ich denke, wir können mitmachen,
MessageFormat.format
da es sowohl in Bezug auf die Lesbarkeit als auch in Bezug auf die Leistung gut sein sollte.Ich habe dasselbe Programm verwendet, das Icaro in seiner obigen Antwort verwendet hat, und es mit angehängtem Code
MessageFormat
zur Erläuterung der Leistungszahlen erweitert.AKTUALISIERUNG:
Gemäß SonarLint Report sollten Zeichenfolgen im Printf-Format korrekt verwendet werden (Tintenfisch: S3457).
Da
printf-style
Formatzeichenfolgen zur Laufzeit interpretiert und nicht vom Compiler überprüft werden, können sie Fehler enthalten, die dazu führen, dass falsche Zeichenfolgen erstellt werden. Diese Regel überprüft statisch die Korrelation vonprintf-style
Formatstrings , um ihre Argumente , wenn das Format (...) Methoden der Aufrufjava.util.Formatter
,java.lang.String
,java.io.PrintStream
,MessageFormat
, undjava.io.PrintWriter
Klassen und dieprintf(...)
Methoden derjava.io.PrintStream
oderjava.io.PrintWriter
Klassen.Ich ersetze den printf-Stil durch die geschweiften Klammern und habe wie unten einige interessante Ergebnisse erhalten.
Mein Fazit:
Wie ich oben hervorgehoben habe, sollte die Verwendung von String.format mit geschweiften Klammern eine gute Wahl sein, um die Vorteile einer guten Lesbarkeit und Leistung zu erzielen.
quelle
Sie können String Concatenation und String.Format mit dem obigen Programm nicht vergleichen.
Sie können dies auch versuchen, indem Sie die Position der Verwendung Ihres String.Format und der Verkettung in Ihrem Codeblock wie unten vertauschen
Sie werden überrascht sein, dass Format hier schneller funktioniert. Dies liegt daran, dass die ursprünglich erstellten Objekte möglicherweise nicht freigegeben werden und ein Problem mit der Speicherzuweisung und damit der Leistung auftreten kann.
quelle
Es dauert ein wenig, bis man sich an String.Format gewöhnt hat, aber es lohnt sich in den meisten Fällen. In der Welt von NRA (wiederholen Sie niemals etwas) ist es äußerst nützlich, Ihre tokenisierten Nachrichten (Protokollierung oder Benutzer) in einer konstanten Bibliothek zu speichern (ich bevorzuge eine statische Klasse) und sie bei Bedarf mit String.Format aufzurufen, unabhängig davon, ob Sie lokalisieren oder nicht. Der Versuch, eine solche Bibliothek mit einer Verkettungsmethode zu verwenden, ist mit jedem Ansatz, der eine Verkettung erfordert, schwieriger zu lesen, Fehler zu beheben, Korrektur zu lesen und zu verwalten. Ersatz ist eine Option, aber ich bezweifle, dass es performant ist. Nach Jahren der Verwendung ist mein größtes Problem mit String.Format, dass die Länge des Aufrufs unpraktisch lang ist, wenn ich ihn an eine andere Funktion (wie Msg) übergebe. Mit einer benutzerdefinierten Funktion, die als Alias dient, ist dies jedoch leicht zu umgehen .
quelle