Ich habe gerade eine SQL-Abfrage wie diese in meinem Projekt gefunden:
return (new StringBuilder("select id1, " + " id2 " + " from " + " table")).toString();
Erreicht dies StringBuilder
sein Ziel, dh die Speichernutzung zu reduzieren?
Ich bezweifle das, weil im Konstruktor das '+' (String concat Operator) verwendet wird. Benötigt das die gleiche Menge an Speicher wie die Verwendung von String wie im folgenden Code? s Ich habe verstanden, es unterscheidet sich bei der Verwendung StringBuilder.append()
.
return "select id1, " + " id2 " + " from " + " table";
Sind beide Anweisungen in der Speichernutzung gleich oder nicht? Bitte klären Sie.
Danke im Voraus!
Bearbeiten:
Übrigens ist es nicht mein Code . Fand es in einem alten Projekt. Außerdem ist die Abfrage nicht so klein wie die in meinem Beispiel. :) :)
java
string
stringbuilder
Vaandu
quelle
quelle
PreparedStatement
oder etwas Ähnliches: docs.oracle.com/javase/tutorial/jdbc/basics/prepared.htmlAntworten:
Nein überhaupt nicht. Dieser Code wird nicht
StringBuilder
richtig verwendet. (Ich denke, Sie haben es jedoch falsch zitiert; sicherlich gibt es keine Zitateid2
undtable
?)Beachten Sie, dass das Ziel ( in der Regel) ist Speicher zu reduzieren Churn anstatt Gesamtspeicher verwendet, um das Leben eines auf dem Garbage Collector zu erleichtern Bit.
Nein, es wird mehr Speicherabwanderung verursachen als nur das von Ihnen zitierte Straight Concat. (Bis / es sei denn, der JVM-Optimierer
StringBuilder
erkennt, dass das Explizite im Code nicht erforderlich ist, und optimiert es, wenn dies möglich ist.)Wenn der Autor dieses Codes verwenden möchte
StringBuilder
(es gibt Argumente dafür, aber auch dagegen; siehe Hinweis am Ende dieser Antwort), ist es besser, es richtig zu machen (hier gehe ich davon aus, dass es keine Anführungszeichen gibtid2
undtable
):Beachten Sie, dass ich
some_appropriate_size
imStringBuilder
Konstruktor aufgelistet habe , damit er mit genügend Kapazität für den gesamten Inhalt beginnt, den wir anhängen werden. Die Standardgröße, die verwendet wird, wenn Sie keine angeben, beträgt 16 Zeichen.StringBuilder
Dies ist normalerweise zu klein und führt dazu, dass Neuzuweisungen vorgenommen werden müssen, um sich selbst zu vergrößern (IIRC verdoppelt sich im Sun / Oracle-JDK selbst [oder mehr, wenn es weiß, dass es mehr braucht, um ein bestimmtes zu befriedigenappend
] jedes Mal, wenn es keinen Platz mehr hat).Sie haben vielleicht gehört , dass die String - Verkettung wird eine Verwendung
StringBuilder
unter der Decke , wenn mit dem Sun / Oracle - Compiler kompiliert. Dies ist wahr, es wird einsStringBuilder
für den Gesamtausdruck verwendet. Es wird jedoch der Standardkonstruktor verwendet, was bedeutet, dass in den meisten Fällen eine Neuzuweisung erforderlich ist. Es ist jedoch einfacher zu lesen. Beachten Sie, dass dies für eine Reihe von Verkettungen nicht gilt . So wird zum Beispiel eins verwendet :StringBuilder
Es bedeutet grob:
Das ist in Ordnung, obwohl der Standardkonstruktor und die anschließende Neuzuweisung (en) nicht ideal sind, stehen die Chancen gut, dass sie gut genug sind - und die Verkettung ist viel besser lesbar.
Aber das ist nur für einen einzigen Ausdruck. Hierfür
StringBuilder
werden mehrere s verwendet:Das wird so etwas:
... was ziemlich hässlich ist.
Es ist jedoch wichtig, sich daran zu erinnern, dass es bis auf wenige Fälle keine Rolle spielt und die Lesbarkeit (die die Wartbarkeit verbessert) bevorzugt wird, sofern kein bestimmtes Leistungsproblem vorliegt.
quelle
x + y + z
Ausdruck verwenden, es seiStringBuilder
denn, ich hätte guten Grund zu der Annahme, dass dies ein bedeutendes Problem sein würde.StringBuilder sql = new StringBuilder(" XXX); sql.append("nndmn");...
. Ähnlichesql.append
Zeilen sind ungefähr 60 Zeilen. Ist das in Ordnung?StringBuilder
zunächst genügend Platz für die Zeichenfolge zugewiesen wird, die Sie dem Konstruktor übergeben haben, plus 16 Zeichen. Wenn Sie also mehr als 16 Zeichen anhängen (ich glaube, Sie sind es, wenn es 60 Anhänge gibt!), Muss dasStringBuilder
mindestens einmal und möglicherweise viele Male neu zugewiesen werden. Wenn Sie eine vernünftige Vorstellung davon haben, wie groß das Endergebnis sein wird (z. B. 400 Zeichen), tun Sie am bestensql = new StringBuilder(400);
(oder was auch immer) dasappend
s.StringBuilder
dass im Voraus etwa acht Speicherzuordnungen eingespart werden (vorausgesetzt, die anfängliche Zeichenfolge besteht aus etwa 10 Zeichen, wäre der SB zunächst 26 gewesen und dann auf 52, dann auf 104, 208 verdoppelt worden). 416, 832, 1664, 3328 und schließlich 6656). Nur wichtig, wenn dies ein Hotspot ist, aber dennoch, wenn Sie im Voraus wissen ... :-)Wenn Sie bereits alle "Teile" haben, die Sie anhängen möchten, macht es keinen Sinn, sie
StringBuilder
überhaupt zu verwenden. Die VerwendungStringBuilder
und Verkettung von Zeichenfolgen im selben Aufruf wie in Ihrem Beispielcode ist noch schlimmer.Das wäre besser:
In diesem Fall findet die Verkettung der Zeichenfolgen ohnehin zur Kompilierungszeit statt , sodass sie dem noch einfacheren entspricht:
Mit Hilfe
new StringBuilder().append("select id1, ").append(" id2 ")....toString()
tatsächlich behindern Leistung in diesem Fall, da es die Verkettung an durchgeführt wird , zwingt die Ausführungszeit , statt bei der Kompilierung Zeit. Hoppla.Wenn der reale Code eine SQL-Abfrage erstellt, indem Werte in die Abfrage aufgenommen werden, ist dies ein weiteres separates Problem: Sie sollten parametrisierte Abfragen verwenden und die Werte in den Parametern und nicht in SQL angeben.
Ich habe einen Artikel über
String
/StringBuffer
den ich vor einiger Zeit geschrieben habe - bevor ich mitgekommen binStringBuilder
. Die Grundsätze gelten jedochStringBuilder
in gleicher Weise.quelle
[[Hier gibt es einige gute Antworten, aber ich finde, dass ihnen noch ein paar Informationen fehlen. ]]
Wie Sie hervorheben, ist das Beispiel, das Sie geben, vereinfachend, aber lassen Sie es uns trotzdem analysieren. Was hier passiert, ist, dass der Compiler die
+
Arbeit hier tatsächlich erledigt , weil"select id1, " + " id2 " + " from " + " table"
alle Konstanten sind. Das wird also zu:In diesem Fall macht es offensichtlich keinen Sinn, sie zu verwenden
StringBuilder
. Sie könnten genauso gut tun:Selbst wenn Sie Felder oder andere Nichtkonstanten anhängen würden, würde der Compiler ein internes verwenden
StringBuilder
- Sie müssen keines definieren:Unter der Decke wird daraus Code, der ungefähr gleichbedeutend ist mit:
Wirklich das einzige Mal, dass Sie
StringBuilder
direkt verwenden müssen, ist, wenn Sie bedingten Code haben. Zum Beispiel ist Code, der wie folgt aussieht, verzweifelt nachStringBuilder
:Das
+
in der ersten Zeile verwendet eineStringBuilder
Instanz. Dann verwendet der+=
eine andereStringBuilder
Instanz. Es ist effizienter zu tun:Ein anderes Mal,
StringBuilder
wenn ich a verwende, erstelle ich eine Zeichenfolge aus einer Reihe von Methodenaufrufen. Dann kann ich Methoden erstellen, die einStringBuilder
Argument annehmen :Wenn Sie a verwenden
StringBuilder
, sollten Sie+
gleichzeitig auf die Verwendung von achten:Dadurch
+
wird ein weiteres internesStringBuilder
erstellt. Dies sollte natürlich sein:Schließlich sollten Sie, wie @TJrowder hervorhebt, immer die Größe des erraten
StringBuilder
. Dies spart die Anzahl derchar[]
Objekte, die beim Vergrößern des internen Puffers erstellt werden.quelle
Sie vermuten zu Recht, dass das Ziel der Verwendung von String Builder nicht erreicht wird, zumindest nicht in vollem Umfang.
Wenn der Compiler jedoch den Ausdruck sieht
"select id1, " + " id2 " + " from " + " table"
, gibt er Code aus, der tatsächlich einenStringBuilder
Blick hinter die Kulissen wirft und an diesen anhängt, sodass das Endergebnis nicht so schlecht ist.Aber natürlich muss jeder, der sich diesen Code ansieht, denken, dass er irgendwie verzögert ist.
quelle
In dem Code, den Sie gepostet haben, gibt es keine Vorteile, da Sie den StringBuilder missbrauchen. In beiden Fällen erstellen Sie denselben String. Mit StringBuilder können Sie die
+
Operation für Strings mithilfe derappend
Methode vermeiden . Sie sollten es so verwenden:In Java ist der String-Typ eine unveränderliche Folge von Zeichen. Wenn Sie also zwei Strings hinzufügen, erstellt die VM einen neuen String-Wert, wobei beide Operanden verkettet sind.
StringBuilder bietet eine veränderbare Folge von Zeichen, mit der Sie verschiedene Werte oder Variablen zusammenfassen können, ohne neue String-Objekte zu erstellen. Daher ist StringBuilder manchmal effizienter als das Arbeiten mit Strings
Dies bietet einige nützliche Funktionen, z. B. das Ändern des Inhalts einer Zeichenfolge, die als Parameter in einer anderen Methode übergeben wird, was mit Strings nicht möglich ist.
Weitere Informationen finden Sie unter http://docs.oracle.com/javase/tutorial/java/data/buffers.html
quelle
+
, die ohnehin in denselben Code konvertiert wird.StringBuilder
ist nützlich, wenn Sie nicht die gesamte Verkettung in einem einzelnen Ausdruck ausführen können, in diesem Fall jedoch nicht.StringBuilder
wenn Sie verwenden würdenreturn "select id1, " + foo + "something else" + bar;
- warum also nicht? Die Frage gibt keinen Hinweis darauf, dass irgendetwas weitergegeben werden mussStringBuilder
.Sie können auch verwenden Message zu
quelle