Während meiner Arbeit mit Datenbanken habe ich festgestellt, dass ich Abfragezeichenfolgen schreibe und in diese Zeichenfolgen muss ich die where-Klausel aus einer Liste / einem Array / einer Sammlung mit mehreren Einschränkungen versehen. Sollte so aussehen:
select * from customer
where customer.id in (34, 26, ..., 2);
Sie können dies vereinfachen, indem Sie dies auf die Frage reduzieren, dass Sie eine Sammlung von Zeichenfolgen haben und eine durch Kommas getrennte Liste dieser Zeichenfolgen in nur einer Zeichenfolge erstellen möchten.
Mein Ansatz, den ich bisher verwendet habe, ist ungefähr so:
String result = "";
boolean first = true;
for(String string : collectionOfStrings) {
if(first) {
result+=string;
first=false;
} else {
result+=","+string;
}
}
Aber das ist, wie Sie sehen können, sehr hässlich. Sie können auf den ersten Blick nicht sehen, was dort passiert, insbesondere wenn die erstellten Zeichenfolgen (wie jede SQL-Abfrage) kompliziert werden.
Was ist Ihre (elegantere) Art?
Antworten:
Hinweis: Diese Antwort war gut, als sie vor 11 Jahren geschrieben wurde, aber jetzt gibt es weitaus bessere Möglichkeiten, dies sauberer in einer einzigen Zeile zu tun, sowohl mit integrierten Java-Klassen als auch mit einer Dienstprogrammbibliothek. Siehe andere Antworten unten.
Da Zeichenfolgen unveränderlich sind, können Sie die StringBuilder-Klasse verwenden, wenn Sie die Zeichenfolge im Code ändern möchten.
Die StringBuilder-Klasse kann als veränderbares String-Objekt angesehen werden, das mehr Speicher reserviert, wenn sein Inhalt geändert wird.
Der ursprüngliche Vorschlag in der Frage kann noch deutlicher und effizienter geschrieben werden, indem das redundante nachfolgende Komma berücksichtigt wird :
quelle
Verwenden Sie die Google Guava API ‚s -
join
Methode:quelle
Joiner
; google-collections.googlecode.com/svn/trunk/javadoc/com/google/…Ich habe mir gerade den Code angesehen, der dies heute getan hat. Dies ist eine Variation der Antwort von AviewAnew.
Die von uns verwendeten StringUtils (<- commons.lang 2.x oder commons.lang 3.x link ) stammen von Apache Commons .
quelle
Die Art und Weise, wie ich diese Schleife schreibe, ist:
Mach dir keine Sorgen über die Leistung von sep. Eine Aufgabe ist sehr schnell. Hotspot neigt ohnehin dazu, die erste Iteration einer Schleife abzuziehen (da es häufig mit Kuriositäten wie Null- und mono- / bimorphen Inlining-Prüfungen zu tun hat).
Wenn Sie es häufig (mehrmals) verwenden, legen Sie es in einer gemeinsamen Methode ab.
Es gibt eine weitere Frage zum Stackoverflow, die sich mit dem Einfügen einer Liste von IDs in eine SQL-Anweisung befasst.
quelle
Seit Java 8 können Sie Folgendes verwenden:
String String.join(CharSequence delimiter, CharSequence... elements)
String String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
Wenn Sie Nicht-
String
s nehmen und sie mit a verbinden möchtenString
, können SieCollectors.joining(CharSequence delimiter)
z.String joined = anyCollection.stream().map(Object::toString).collect(Collectors.joining(","));
quelle
cats.stream().map(cat -> cat.getName()).collect(Collectors.joining(","));
für eine einzelne Variable aus Ihrer Sammlung.stream
. Für int [] oder long [] oder andere Arrays, in die der Wert einfach umgewandelt werden kannString
, würde ich nach einer Nicht-Streaming-Lösung suchen. Tatsächlich suche ich.Ich fand das Iterator-Idiom elegant, weil es einen Test für mehr Elemente enthält (aus Gründen der Kürze wurde der Null- / Leer-Test nicht angegeben):
quelle
Es gibt viele manuelle Lösungen dafür, aber ich wollte Julies Antwort oben wiederholen und aktualisieren. Verwenden Sie die Joiner-Klasse für Google-Sammlungen .
Es verarbeitet var args, iterables und arrays und behandelt Trennzeichen von mehr als einem Zeichen ordnungsgemäß (im Gegensatz zu gimmels Antwort). Bei Bedarf werden auch Nullwerte in Ihrer Liste verarbeitet.
quelle
Hier ist eine unglaublich generische Version, die ich aus einer Kombination der vorherigen Vorschläge erstellt habe:
quelle
verfügbar in der Java8-API.
Alternative zu (ohne dass eine Google Guava-Abhängigkeit hinzugefügt werden muss):
quelle
Du könntest es versuchen
quelle
Dies ist die bisher kürzeste Lösung, mit Ausnahme der Verwendung von Guava oder Apache Commons
Gut mit 0,1 und n Elementliste. Sie müssen jedoch nach einer Nullliste suchen. Ich benutze dies in GWT, also bin ich dort gut ohne StringBuilder. Und für kurze Listen mit nur ein paar Elementen ist es auch anderswo in Ordnung;)
quelle
Für den Fall, dass jemand in jüngerer Zeit darüber gestolpert ist, habe ich eine einfache Variante mit Java 8 hinzugefügt
reduce()
. Es enthält auch einige der bereits erwähnten Lösungen anderer:quelle
In Android sollten Sie Folgendes verwenden:
quelle
Ich denke, es ist keine gute Idee, das SQL so zu konstruieren, dass es die Werte der where-Klausel verkettet, wie Sie es tun:
Woher
valueX
kommt eine Liste von Strings.Erstens, wenn Sie Strings vergleichen, müssen sie in Anführungszeichen gesetzt werden. Dies ist nicht trivial, wenn die Strings ein Zitat enthalten könnten.
Zweitens ist ein SQL-Injection-Angriff möglich, wenn die Werte vom Benutzer oder einem anderen System stammen.
Es ist viel ausführlicher, aber Sie sollten einen String wie den folgenden erstellen:
und binden Sie dann die Variablen mit
Statement.setString(nParameter,parameterValue)
.quelle
Nur eine andere Methode, um dieses Problem zu lösen. Nicht die kürzeste, aber es ist effizient und erledigt die Arbeit.
quelle
Es gibt einige Java-Bibliotheken von Drittanbietern, die eine String-Join-Methode bereitstellen, aber Sie möchten eine Bibliothek wahrscheinlich nicht nur für so etwas Einfaches verwenden. Ich würde nur eine Hilfsmethode wie diese erstellen, die meiner Meinung nach etwas besser ist als Ihre Version. Sie verwendet StringBuffer, der effizienter ist, wenn Sie viele Zeichenfolgen verbinden müssen, und funktioniert für eine Sammlung eines beliebigen Typs.
Ein weiterer Vorschlag zur Verwendung von Collection.toString () ist kürzer. Dies setzt jedoch voraus, dass Collection.toString () eine Zeichenfolge in einem ganz bestimmten Format zurückgibt, auf das ich mich persönlich nicht verlassen möchte.
quelle
Wenn Sie Spring verwenden, können Sie Folgendes tun:
(Paket org.springframework.util)
quelle
Ich bin mir nicht sicher, wie "raffiniert" das ist, aber es ist sicherlich etwas kürzer. Es funktioniert mit verschiedenen Arten von Sammlungen, z. B. Set <Integer>, List <String> usw.
Übung für den Leser : Ändern Sie diese Methode so, dass sie eine null / leere Sammlung korrekt behandelt :)
quelle
Was den Code hässlich macht, ist die spezielle Behandlung für den ersten Fall. Die meisten Zeilen in diesem kleinen Ausschnitt widmen sich nicht der Routinearbeit des Codes, sondern der Behandlung dieses Sonderfalls. Und genau das lösen Alternativen wie die von Gimel, indem sie das spezielle Handling außerhalb der Schleife bewegen. Es gibt einen Sonderfall (nun, Sie könnten sowohl Start als auch Ende als Sonderfälle betrachten - aber nur einer von ihnen muss speziell behandelt werden), sodass die Behandlung innerhalb der Schleife unnötig kompliziert ist.
quelle
Ich habe gerade eingecheckt in einem Test für meine Bibliothek Dollar :
Mit nur einem statischen Import wird ein fließender Wrapper um Listen / Arrays / Strings / etc erstellt :
$
.NB :
Unter Verwendung von Bereichen kann die vorherige Liste als neu geschrieben werden
$(1, 5).join(",")
quelle
Das Schöne am IN-Ausdruck ist, dass sich das Ergebnis nicht ändert, wenn Sie wiederholte Werte haben. Duplizieren Sie einfach das erste Element und verarbeiten Sie die gesamte Liste. Dies setzt voraus, dass mindestens ein Element in der Liste vorhanden ist. Wenn es keine Elemente gibt, würde ich vorschlagen, zuerst danach zu suchen und dann die SQL überhaupt nicht auszuführen.
Dies wird den Trick machen, ist offensichtlich in dem, was es tut und verlässt sich nicht auf externe Bibliotheken:
quelle
Während ich denke, dass Ihre beste Wette darin besteht, Joiner von Guava zu verwenden, finde ich diesen Ansatz eleganter, wenn ich ihn von Hand codiere, als die 'erste' Flagge oder das letzte Komma abzuschneiden.
quelle
Wenn Sie ein Array haben, können Sie Folgendes tun:
quelle
Eine weitere Option, basierend auf dem, was ich hier sehe (mit geringfügigen Änderungen).
quelle
Join-Methoden sind in Arrays und den Klassen verfügbar, die
AbstractCollections
dietoString()
Methode erweitern , aber nicht überschreiben (wie praktisch alle Sammlungen injava.util
).Zum Beispiel:
Das ist ziemlich seltsam, da es nur für Zahlen funktioniert, die SQL-ähnlich sind.
quelle
StringUtils von springframeowrk: Federkern
quelle
Möglicherweise können Sie LINQ (zu SQL) verwenden und das Dynamic Query LINQ-Beispiel von MS verwenden. http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
quelle
quelle
quelle
List token = new ArrayList (Ergebnis); final StringBuilder builder = new StringBuilder ();
builder.toString ();
quelle