Während ich in einer Java-App arbeitete, musste ich kürzlich eine durch Kommas getrennte Liste von Werten zusammenstellen, um sie an einen anderen Webdienst zu übergeben, ohne vorher zu wissen, wie viele Elemente vorhanden sein würden. Das Beste, was ich mir auf den Kopf stellen konnte, war ungefähr so:
public String appendWithDelimiter( String original, String addition, String delimiter ) {
if ( original.equals( "" ) ) {
return addition;
} else {
return original + delimiter + addition;
}
}
String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );
Mir ist klar, dass dies nicht besonders effizient ist, da überall Zeichenfolgen erstellt werden, aber ich wollte mehr Klarheit als Optimierung.
In Ruby kann ich stattdessen so etwas tun, was sich viel eleganter anfühlt:
parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");
Da Java jedoch keinen Join-Befehl hat, konnte ich nichts Äquivalentes herausfinden.
Was ist der beste Weg, dies in Java zu tun?
Antworten:
Vor Java 8:
Apaches Commons Lang ist hier Ihr Freund - es bietet eine Join-Methode, die der in Ruby genannten sehr ähnlich ist:
StringUtils.join(java.lang.Iterable,char)
Java 8:
Java 8 bietet sofortiges Beitreten über
StringJoiner
undString.join()
. Die folgenden Ausschnitte zeigen, wie Sie sie verwenden können:StringJoiner
String.join(CharSequence delimiter, CharSequence... elements))
String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
quelle
Sie könnten eine kleine Dienstprogrammmethode im Join-Stil schreiben, die für java.util.Lists funktioniert
Dann benutze es so:
quelle
List<String>
Ihren Intitializer nicht aufIterator<?>
den gleichen Effekt umstellen ?Im Fall von Android ist die StringUtils-Klasse von Commons nicht verfügbar, daher habe ich dies verwendet
http://developer.android.com/reference/android/text/TextUtils.html
quelle
Die Guava-Bibliothek von Google enthält com.google.common.base.Joiner Klasse , mit deren Hilfe solche Aufgaben gelöst werden können.
Proben:
Hier ist ein Artikel über die String-Dienstprogramme von Guava .
quelle
In Java 8 können Sie Folgendes verwenden
String.join()
:Schauen Sie sich auch diese Antwort für ein Stream-API-Beispiel an.
quelle
Sie können es verallgemeinern, aber es gibt keine Verknüpfung in Java, wie Sie gut sagen.
Dies könnte besser funktionieren.
quelle
Iterable<String>
und verwenden Sie einfach die Tatsache, dass Sie darüber iterieren können. In Ihrem Beispiel benötigen Sie nicht die Anzahl der Elemente in der Sammlung, daher ist dies noch allgemeiner.StringBuilder
stattdessen ein verwenden. Sie sind identisch,StringBuffer
bieten jedoch unnötige Gewindesicherheit. Kann jemand es bitte bearbeiten!isEmpty()
Methode, verwenden Sienext()
stattdessen die MethodeIn Java 8 können Sie dies wie folgt tun:
Wenn die Liste Nullen enthält, können Sie Folgendes verwenden:
Es unterstützt auch Präfix und Suffix:
quelle
Verwenden Sie einen Ansatz basierend auf
java.lang.StringBuilder
! ("Eine veränderbare Folge von Zeichen.")Wie Sie bereits erwähnt haben, erzeugen all diese String-Verkettungen überall Strings.
StringBuilder
werde das nicht tun.Warum
StringBuilder
stattStringBuffer
? Aus demStringBuilder
Javadoc:quelle
Ich würde Google Collections verwenden. Es gibt eine schöne Join-Einrichtung.
http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/base/Join.html
Aber wenn ich es selbst schreiben wollte,
Ich denke, es funktioniert besser mit einer Objektsammlung, da Sie Ihre Objekte jetzt nicht mehr in Zeichenfolgen konvertieren müssen, bevor Sie sie verbinden.
quelle
Die StringUtils-Klasse von Apache Commons verfügt über eine Join-Methode.
quelle
Java 8
quelle
Sie können hierfür den Java-
StringBuilder
Typ verwenden. Es gibt auchStringBuffer
, aber es enthält zusätzliche Thread-Sicherheitslogik, die oft unnötig ist.quelle
Und eine minimale (wenn Sie Apache Commons oder Gauva nicht in Projektabhängigkeiten aufnehmen möchten, nur um Zeichenfolgen zu verbinden)
quelle
Verwenden Sie StringBuilder und class
Separator
Das Trennzeichen umschließt ein Trennzeichen. Das Trennzeichen wird von der Separator-
toString
Methode zurückgegeben, es sei denn, beim ersten Aufruf wird die leere Zeichenfolge zurückgegeben!Quellcode für die Klasse
Separator
quelle
Separator
, bei der eineStringBuilder
anstelle einer Verkettung verwendet wirdStrings
?Separator
nur das Trennzeichen zurück, es verkettet die Zeichenfolge selbst nicht.Separator
??? Warum nicht einfach einen einfachen String verwenden ..?!Warum schreiben Sie nicht Ihre eigene join () -Methode? Es würde als Parameter Sammlung von Strings und einem Trennzeichen String verwenden. Innerhalb der Methode durchlaufen Sie die Sammlung und bauen Ihr Ergebnis in einem StringBuffer auf.
quelle
Wenn Sie Spring MVC verwenden, können Sie die folgenden Schritte ausführen.
Es wird dazu führen
a,b,c
quelle
Wenn Sie Eclipse-Sammlungen verwenden , können Sie
makeString()
oder verwendenappendString()
.makeString()
gibt eineString
Darstellung zurück, ähnlich wietoString()
.Es hat drei Formen
makeString(start, separator, end)
makeString(separator)
Standardmäßig beginnen und enden leere ZeichenfolgenmakeString()
Der Standardwert für das Trennzeichen ist", "
(Komma und Leerzeichen).Codebeispiel:
appendString()
ist ähnlichmakeString()
, aber es hängt an einAppendable
(wieStringBuilder
) und istvoid
. Es hat die gleichen drei Formen, mit einem zusätzlichen ersten Argument, dem Anhang.Wenn Sie Ihre Sammlung nicht in einen Eclipse-Sammlungstyp konvertieren können, passen Sie sie einfach mit dem entsprechenden Adapter an.
Hinweis: Ich bin ein Committer für Eclipse-Sammlungen.
quelle
Java 8 Native Type
Benutzerdefiniertes Java 8-Objekt:
quelle
Sie sollten wahrscheinlich a
StringBuilder
mit derappend
Methode verwenden, um Ihr Ergebnis zu erstellen, aber ansonsten ist dies eine ebenso gute Lösung wie Java.quelle
Warum machen Sie in Java nicht dasselbe wie in Ruby, dh die durch Trennzeichen getrennte Zeichenfolge wird erst erstellt, nachdem Sie alle Teile zum Array hinzugefügt haben?
Möglicherweise möchten Sie diese for-Schleife in einer separaten Hilfsmethode verschieben und anstelle von StringBuffer auch StringBuilder verwenden ...
Bearbeiten : Die Reihenfolge der Anhänge wurde korrigiert.
quelle
Mit Java 5-Variablenargumenten müssen Sie also nicht alle Zeichenfolgen explizit in eine Sammlung oder ein Array einfügen:
quelle
Für diejenigen, die sich in einem Frühlingskontext befinden, ihre StringUtils Klasse ebenfalls nützlich:
Es gibt viele nützliche Verknüpfungen wie:
und viele andere.
Dies kann hilfreich sein, wenn Sie Java 8 noch nicht verwenden und sich bereits in einem Spring-Kontext befinden.
Ich bevorzuge es gegen die Apache Commons (obwohl auch sehr gut) für die Collection-Unterstützung, die so einfacher ist:
quelle
Sie können so etwas ausprobieren:
quelle
Also im Grunde so etwas:
quelle
Ich weiß nicht, ob dies wirklich besser ist, aber zumindest wird StringBuilder verwendet, was möglicherweise etwas effizienter ist.
Unten finden Sie einen allgemeineren Ansatz, wenn Sie die Liste der Parameter erstellen können, bevor Sie eine Parameterbegrenzung vornehmen.
quelle
Ihr Ansatz ist nicht schlecht, aber Sie sollten einen StringBuffer anstelle des + -Zeichens verwenden. Das + hat den großen Nachteil, dass für jede einzelne Operation eine neue String-Instanz erstellt wird. Je länger Ihre Saite wird, desto größer ist der Overhead. Die Verwendung eines StringBuffers sollte also der schnellste Weg sein:
Nachdem Sie Ihre Zeichenfolge erstellt haben, rufen Sie einfach toString () für den zurückgegebenen StringBuffer auf.
quelle
Anstatt die Verkettung von Zeichenfolgen zu verwenden, sollten Sie StringBuilder verwenden, wenn Ihr Code nicht mit einem Thread versehen ist, und StringBuffer, wenn dies der Fall ist.
quelle
Du machst das etwas komplizierter als es sein muss. Beginnen wir mit dem Ende Ihres Beispiels:
Mit der kleinen Änderung, einen StringBuilder anstelle eines Strings zu verwenden, wird dies zu:
Wenn Sie fertig sind (ich nehme an, Sie müssen auch einige andere Bedingungen überprüfen), stellen Sie einfach sicher, dass Sie das Endkomma mit einem Befehl wie dem folgenden entfernen:
Und zum Schluss holen Sie sich den gewünschten String
Sie können das "," im zweiten Aufruf zum Anhängen auch durch eine generische Trennzeichenfolge ersetzen, die auf einen beliebigen Wert festgelegt werden kann. Wenn Sie eine Liste von Dingen haben, von denen Sie wissen, dass Sie sie anhängen müssen (nicht bedingt), können Sie diesen Code in eine Methode einfügen, die eine Liste von Zeichenfolgen enthält.
quelle
quelle
Also ein paar Dinge, die Sie tun könnten, um das Gefühl zu bekommen, dass Sie suchen:
1) Erweitern Sie die List-Klasse - und fügen Sie die Join-Methode hinzu. Die Join-Methode würde einfach die Arbeit des Verkettens und Hinzufügens des Trennzeichens erledigen (was ein Parameter für die Join-Methode sein könnte).
2) Es sieht so aus, als würde Java 7 Java Erweiterungsmethoden hinzufügen - mit denen Sie einfach eine bestimmte Methode an eine Klasse anhängen können: Sie können diese Join-Methode also schreiben und als Erweiterungsmethode zu List oder sogar zu hinzufügen Sammlung.
Lösung 1 ist jetzt wahrscheinlich die einzig realistische, da Java 7 noch nicht verfügbar ist :) Aber es sollte gut funktionieren.
Um beide zu verwenden, fügen Sie einfach alle Ihre Elemente wie gewohnt zur Liste oder Sammlung hinzu und rufen dann die neue benutzerdefinierte Methode auf, um sie zu verbinden.
quelle