Korrekten Verwendung von StringBuilder-Objekt in SQL
Fand ich einige sql-Abfrage bauen, wie dies in meinem Projekt:
return (new StringBuilder("select id1, " + " id2 " + " from " + " table")).toString();
Tut dies StringBuilder
erreichen, ich.e Verringerung der Speichernutzung?
Bezweifle ich, denn in dem Konstruktor der '+' (String-concat-operator) verwendet. Wird, dass die gleiche Menge Speicher wie die Verwendung von Zeichenfolgen, wie Sie den code unten? s ich verstanden, es ist unterschiedlich, wenn Sie mit StringBuilder.append()
.
return "select id1, " + " id2 " + " from " + " table";
Sind beide Aussagen gleich in memory usage oder nicht? Bitte klären Sie.
Vielen Dank im Voraus!
Edit:
BTW, es ist nicht mein code. Fand es in einem alten Projekt. Auch, die Abfrage ist nicht so klein, wie in meinem Beispiel. 🙂
- SQL-SICHERHEIT: verwenden Sie immer
PreparedStatement
oder etwas ähnliches: docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html - Abgesehen von der Speichernutzung Sache, warum nicht verwenden Sie einen SQL-builder-Bibliothek statt: stackoverflow.com/q/370818/521799
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nein, überhaupt nicht. Dieser code wird nicht mit
StringBuilder
richtig. (Ich glaube, du hast falsch zitiert es, aber sicherlich gibt es nicht in Anführungszeichenid2
undtable
?)Beachten Sie, dass das Ziel (in der Regel) zu reduzieren, - Speicher churn eher als der gesamte Speicher genutzt, um das Leben ein bisschen einfacher auf den garbage collector.
Nein, es werden Ursache mehr Speicher Abwanderung als nur die gerade concat, die Sie verstehen. (Bis/es sei denn, der JVM-Optimierer sieht, dass das explizite
StringBuilder
im code ist überflüssig und optimiert es aus, wenn man es kann.)Wenn der Autor des Codes verwenden will
StringBuilder
(es gibt Argumente für, aber auch gegen; siehe Hinweis am Ende dieser Antwort), besser, es richtig zu machen (hier gehe ich davon aus dass es eigentlich nicht in Anführungszeichenid2
undtable
):Beachten Sie, dass ich aufgeführt habe
some_appropriate_size
imStringBuilder
Konstruktor, so dass es beginnt, mit genug Kapazität für den gesamten Inhalt, den wir gehen, zum Anhängen. Die default-Größe verwendet, wenn Sie nicht angeben, ist 16 Zeichen, die in der Regel zu klein und die Ergebnisse in dieStringBuilder
sich nicht um die Umschichtungen selbst zu machen, größer (wenn ich mich Recht erinnere, in der Sun/Oracle-JDK, verdoppelt sich [oder mehr, wenn es weiß, braucht es mehr, um einen bestimmtenappend
] jedes mal, es läuft aus dem Zimmer).Können Sie gehört haben, dass die string-Verkettung wird Verwendung eines
StringBuilder
unter der Decke, wenn kompiliert mit Sun/Oracle-compiler. Das ist wahr, es wird mit einerStringBuilder
für den gesamten Ausdruck. Aber es wird der Standard-Konstruktor, was bedeutet, dass in der Mehrzahl der Fälle wird es um eine Umverteilung. Es ist leichter zu Lesen, obwohl. Beachten Sie, dass dies nicht von einer echten Serie von Verkettungen. So zum Beispiel, nutzt diese eineStringBuilder
:Es übersetzt in etwa:
So, dass ist okay, auch wenn die Standard-Konstruktor und anschließende Umverteilung(s) ist nicht ideal, sind die Chancen, es ist gut genug — und die Verkettung ist ein viel mehr lesbar.
Aber das ist nur für einen einzigen Ausdruck. Mehrere
StringBuilder
s werden verwendet:Dass am Ende immer so etwas wie dieses:
...das ist ziemlich hässlich.
Es ist wichtig zu beachten Sie jedoch, dass in allen, aber ganz wenigen Fällen es egal und gehen mit der Lesbarkeit (das erhöht die Wartbarkeit) wird bevorzugt, abgesehen von einer spezifischen performance-Problem.
x + y + z
Ausdruck eher alsStringBuilder
es sei denn, ich hatte guten Grund zu der Annahme, es wäre ein wichtiges Thema.StringBuilder sql = new StringBuilder(" XXX); sql.append("nndmn");...
. Ähnlichesql.append
Linien sind rund 60 Zeilen. Ist dieser in Ordnung?StringBuilder
wird zunächst reserviert genug Platz für den string, den Sie übergeben dem Konstruktor plus 16 Zeichen. Also, wenn Sie fügen Sie mehr als 16 Zeichen (ich wage zu sagen, Sie sind, wenn es 60 hängt!), dieStringBuilder
haben Neuzuordnung mindestens einmal, und möglicherweise viele Male. Wenn man eine vernünftige Vorstellung davon, wie groß das Endergebnis sein wird (sagen wir, 400 Zeichen), es ist am besten zu tunsql = new StringBuilder(400);
(oder was auch immer) dann tun Sie dasappend
s.StringBuilder
dass Sie im Voraus sparen über acht Speicher-Umschichtungen (vorausgesetzt, der ursprüngliche string war über 10 Zeichen, die SB hätte 26, mit zu beginnen, dann verdoppelte sich auf 52, dann 104, 208, 416, 832, 1664, 3328, und schließlich 6656). Nur von Bedeutung, wenn dies ist ein hotspot, aber immer noch, wenn Sie im Voraus wissen... 🙂StringBuilder
für, die, anstattString
gehören ein Konstruktor des TypsString[]
? Für eine beliebige Anzahl von Argumenten von jeder Größe, wird die Summe der GC-Abwanderung aus dem zweiten Ansatz, wäre ein array von Referenzen auf strings. Durch Kontrast, mit einem StringBuilder garantiert eine Abwanderung der mindestens gleich der Größe des resultierenden Strings.Wenn Sie bereits alle "Stücke", die Sie Anhängen wollen, gibt es keinen Punkt in mit
StringBuilder
überhaupt. MitStringBuilder
und string-Verkettung in den gleichen Ruf wie pro Ihre sample-code ist noch schlimmer.Besser wäre:
In diesem Fall, die string-Verkettung ist eigentlich passiert compile-Zeit sowieso, also ist es äquivalent zu der auch einfacher:
Mit
new StringBuilder().append("select id1, ").append(" id2 ")....toString()
tatsächlich behindern Leistung in diesem Fall, weil es zwingt die Verkettung durchgeführt werden Ausführungszeit, statt auf kompilieren Zeit. Oops.Wenn der wirkliche code ist der Aufbau einer SQL-Abfrage durch, einschließlich Werte in die Abfrage, dann ist das eine andere separate Problem ist, dass Sie sollten mit parametrisierten Abfragen, Angabe der Werte in den Parametern, anstatt in die SQL.
Ich habe eine Artikel auf
String
/StringBuffer
, die ich vor einiger Zeit geschrieben - vorStringBuilder
kam. Die Grundsätze gelten fürStringBuilder
in der gleichen Weise, obwohl.[[ Es gibt einige gute Antworten hier, aber ich finde, dass Sie immer noch fehlt ein bisschen information. ]]
So wie Sie, das Beispiel, das Sie geben, ist eine einfache, aber analysieren wir es trotzdem. Was hier passiert, ist die compiler eigentlich die
+
Arbeit hier, weil"select id1, " + " id2 " + " from " + " table"
sind alle Konstanten. Also diese verwandelt sich in:In diesem Fall, es gibt natürlich keinen Punkt in mit
StringBuilder
. Sie könnten das auch tun:Jedoch, auch wenn man anfügen von beliebigen Feldern oder anderen nicht-Konstanten, dann würde der compiler die Verwendung einer internen
StringBuilder
-- es gibt keine Notwendigkeit für Sie zu definieren:Unter der Decke, diese verwandelt sich in code, entspricht etwa:
Wirklich die einzige Zeit, die Sie brauchen, um zu verwenden
StringBuilder
direkt ist, wenn Sie bedingten code. Für Beispiel-code, der wie folgt aussieht ist verzweifelt für eineStringBuilder
:Den
+
in der ersten Zeile verwendet manStringBuilder
Instanz. Dann die+=
verwendet eine andereStringBuilder
Instanz. Es ist effizienter, das zu tun:Einem anderen Zeitpunkt, ich benutze eine
StringBuilder
ist, wenn ich Baue einen string aus einer Reihe von Methodenaufrufen. Dann kann ich Methoden erstellen, nehmen Sie eineStringBuilder
argument:Wenn Sie eine
StringBuilder
, Sie sollten sehen in der Verwendung von+
zur gleichen Zeit:Dass
+
wird dazu führen, eine andere interneStringBuilder
erstellt werden. Dies sollte selbstverständlich sein:Schließlich ist, wie @T. J. rowder Punkte aus, sollten Sie immer stellen Sie eine Vermutung an, die Größe der
StringBuilder
. Das spart auf die Anzahl derchar[]
erstellte Objekte bei der wachsenden Größe der internen Puffer.Sind Sie richtig erraten, daß es das Ziel der Verwendung von string-generator ist nicht erreicht, zumindest nicht in seinem vollen Umfang.
Allerdings, wenn der compiler auf den Ausdruck
"select id1, " + " id2 " + " from " + " table"
es strahlt code, der erstellt tatsächlich eineStringBuilder
hinter die kulissen und fügt an, dass das end-Ergebnis ist nicht so schlimm afterall.Aber natürlich jeder an, dass der code gebunden ist, zu denken, dass es ist irgendwie verzögert.
In dem code, den Sie gepostet haben es wäre keine Vorteile, da Sie missbräuchlich die StringBuilder. Sie bauen die gleiche Zeichenfolge in beiden Fällen. Mit StringBuilder können Sie vermeiden, die
+
Betrieb auf Strings mit derappend
Methode.Sie sollten diese Art der Nutzung:
In Java der Typ String ist ein inmutable Folge von Zeichen, so dass, wenn man zwei Saiten mit der VM erstellt eine neue Zeichenfolge mit beiden Operanden verkettet.
StringBuilder bietet eine veränderbare Abfolge von Zeichen, die Sie verwenden können, um concat verschiedene Werte oder Variablen ohne neue String-Objekte, und so kann es manchmal effizienter sein als das arbeiten mit strings
Dieser bietet einige nützliche Funktionen, wie das ändern der Inhalt einer char-Sequenz als parameter übergeben, die innerhalb einer anderen Methode, die Sie kann nicht mit Strings.
Weitere Infos unter http://docs.oracle.com/javase/tutorial/java/data/buffers.html
+
, die umgewandelt werden, in der gleiche code sowieso.StringBuilder
ist nützlich, wenn Sie nicht erfüllen alle die Verkettung in einem einzigen Ausdruck, aber in diesem Fall nicht.StringBuilder
wenn Sie aufreturn "select id1, " + foo + "something else" + bar;
- warum also nicht? Die Frage enthält keinen Hinweis darauf, dass irgend etwas muss passieren dieStringBuilder
herum.Könnten Sie auch MessageFormat zu