Lorsque je travaillais dans une application Java, j'ai récemment dû assembler une liste de valeurs délimitées par des virgules pour passer à un autre service Web sans savoir combien d'éléments il y aurait à l'avance. Le mieux que j'ai pu trouver du haut de ma tête était quelque chose comme ça:
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", "," );
Je me rends compte que ce n'est pas particulièrement efficace, car il y a des chaînes en cours de création partout, mais j'allais plus pour la clarté que l'optimisation.
Dans Ruby, je peux faire quelque chose comme ça à la place, ce qui est beaucoup plus élégant:
parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");
Mais comme Java n'a pas de commande join, je n'ai rien trouvé d'équivalent.
Alors, quelle est la meilleure façon de le faire en Java?
Réponses:
Pré Java 8:
Apache's commons lang est votre ami ici - il fournit une méthode de jointure très similaire à celle à laquelle vous faites référence dans Ruby:
StringUtils.join(java.lang.Iterable,char)
Java 8:
Java 8 permet de rejoindre dès la sortie de la boîte via
StringJoiner
etString.join()
. Les extraits ci-dessous montrent comment vous pouvez les utiliser:StringJoiner
String.join(CharSequence delimiter, CharSequence... elements))
String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
la source
Vous pouvez écrire une petite méthode utilitaire de style jointure qui fonctionne sur java.util.Lists
Ensuite, utilisez-le comme ceci:
la source
List<String>
votre initialiseur enIterator<?>
et avoir le même effet?Dans le cas d'Android, la classe StringUtils de commons n'est pas disponible, donc pour cela j'ai utilisé
http://developer.android.com/reference/android/text/TextUtils.html
la source
La bibliothèque Google de Guava a com.google.common.base.Joiner classe qui aide à résoudre ces tâches.
Échantillons:
Voici un article sur les utilitaires de chaîne de Guava .
la source
Dans Java 8, vous pouvez utiliser
String.join()
:Jetez également un œil à cette réponse pour un exemple d'API Stream.
la source
Vous pouvez le généraliser, mais il n'y a pas de jointure en Java, comme vous le dites bien.
Cela pourrait mieux fonctionner.
la source
Iterable<String>
et utilisez simplement le fait que vous pouvez itérer dessus. Dans votre exemple, vous n'avez pas besoin du nombre d'articles dans la collection, c'est donc encore plus général.StringBuilder
place. Ils sont identiques, sauf qu'ilsStringBuffer
offrent une sécurité de filetage inutile. Quelqu'un peut-il le modifier!isEmpty()
méthode, utiliseznext()
plutôt la méthodedans Java 8, vous pouvez faire ceci comme:
si la liste a des valeurs nulles, vous pouvez utiliser:
il prend également en charge le préfixe et le suffixe:
la source
Utilisez une approche basée sur
java.lang.StringBuilder
! ("Une séquence de caractères modifiable.")Comme vous l'avez mentionné, toutes ces concaténations de chaînes créent des chaînes partout.
StringBuilder
ne fera pas ça.Pourquoi
StringBuilder
au lieu deStringBuffer
? DuStringBuilder
javadoc:la source
J'utiliserais Google Collections. Il y a une belle installation Join.
http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/base/Join.html
Mais si je voulais l'écrire moi-même,
Je pense que cela fonctionne mieux avec une collection d'objets, car maintenant vous n'avez plus besoin de convertir vos objets en chaînes avant de les rejoindre.
la source
La classe Apache commons StringUtils a une méthode de jointure.
la source
Java 8
la source
Vous pouvez utiliser le
StringBuilder
type Java pour cela. Il y en a aussiStringBuffer
, mais il contient une logique de sécurité de thread supplémentaire qui est souvent inutile.la source
Et un minimum (si vous ne voulez pas inclure Apache Commons ou Gauva dans les dépendances du projet juste pour joindre des chaînes)
la source
Utilisez StringBuilder et la classe
Separator
Le séparateur encapsule un délimiteur. Le délimiteur est retourné par la
toString
méthode du séparateur , sauf lors du premier appel qui retourne la chaîne vide!Code source de la classe
Separator
la source
Separator
pour qu'il utilise unStringBuilder
au lieu de concaténerStrings
?Separator
renvoie simplement le délimiteur, il ne concatène pas la chaîne elle-même.Separator
??? Pourquoi ne pas simplement utiliser une simple chaîne ..?!Pourquoi ne pas écrire votre propre méthode join ()? Il prendrait comme collection de paramètres des chaînes et une chaîne de délimitation. Dans la méthode, parcourez la collection et générez votre résultat dans un StringBuffer.
la source
Si vous utilisez Spring MVC, vous pouvez essayer les étapes suivantes.
Il en résultera
a,b,c
la source
Si vous utilisez des collections Eclipse , vous pouvez utiliser
makeString()
ouappendString()
.makeString()
renvoie uneString
représentation, similaire àtoString()
.Il a trois formes
makeString(start, separator, end)
makeString(separator)
valeurs par défaut de début et de fin pour les chaînes videsmakeString()
par défaut, le séparateur est", "
(virgule et espace)Exemple de code:
appendString()
est similaire àmakeString()
, mais il s'ajoute à unAppendable
(commeStringBuilder
) et l'estvoid
. Il a les trois mêmes formes, avec un premier argument supplémentaire, l'Appendable.Si vous ne pouvez pas convertir votre collection en type de collections Eclipse, adaptez-la simplement avec l'adaptateur approprié.
Remarque: je suis un committer pour les collections Eclipse.
la source
Java 8 Native Type
Objet personnalisé Java 8:
la source
Vous devriez probablement utiliser un
StringBuilder
avec laappend
méthode pour construire votre résultat, mais sinon c'est aussi une bonne solution que Java a à offrir.la source
Pourquoi ne faites-vous pas en Java la même chose que vous faites en ruby, c'est-à-dire créer la chaîne séparée par un délimiteur seulement après avoir ajouté toutes les pièces au tableau?
Vous voudrez peut-être déplacer cela pour la boucle dans une méthode d'assistance distincte, et utiliser également StringBuilder au lieu de StringBuffer ...
Edit : correction de l'ordre des ajouts.
la source
Avec les arguments de variable Java 5, vous n'avez donc pas à remplir toutes vos chaînes dans une collection ou un tableau explicitement:
la source
Pour ceux qui sont dans un contexte Spring, leur classe StringUtils est également utile:
Il existe de nombreux raccourcis utiles tels que:
et plein d'autres.
Cela peut être utile si vous n'utilisez pas déjà Java 8 et que vous êtes déjà dans un contexte Spring.
Je le préfère contre Apache Commons (bien que très bon aussi) pour le support de Collection qui est plus facile comme ceci:
la source
Vous pouvez essayer quelque chose comme ceci:
la source
Donc, fondamentalement, quelque chose comme ça:
la source
Je ne sais pas si c'est vraiment mieux, mais au moins, il utilise StringBuilder, qui peut être légèrement plus efficace.
Vous trouverez ci-dessous une approche plus générique si vous pouvez créer la liste des paramètres AVANT d'effectuer une délimitation de paramètre.
la source
Votre approche n'est pas trop mauvaise, mais vous devez utiliser un StringBuffer au lieu d'utiliser le signe +. Le + a le gros inconvénient qu'une nouvelle instance de chaîne est créée pour chaque opération. Plus votre chaîne est longue, plus les frais généraux sont importants. Donc, utiliser un StringBuffer devrait être le moyen le plus rapide:
Après avoir créé votre chaîne, appelez simplement toString () sur le StringBuffer retourné.
la source
Au lieu d'utiliser la concaténation de chaînes, vous devez utiliser StringBuilder si votre code n'est pas enfilé et StringBuffer si c'est le cas.
la source
Vous rendez cela un peu plus compliqué qu'il ne doit l'être. Commençons par la fin de votre exemple:
Avec le petit changement de l'utilisation d'un StringBuilder au lieu d'une chaîne, cela devient:
Lorsque vous avez terminé (je suppose que vous devez également vérifier quelques autres conditions), assurez-vous de supprimer la virgule de queue avec une commande comme celle-ci:
Et enfin, obtenez la chaîne que vous voulez avec
Vous pouvez également remplacer le "," dans le deuxième appel à ajouter par une chaîne de délimitation générique qui peut être définie sur n'importe quoi. Si vous avez une liste de choses que vous savez que vous devez ajouter (sans condition), vous pouvez mettre ce code dans une méthode qui prend une liste de chaînes.
la source
la source
Donc, quelques choses que vous pourriez faire pour avoir l'impression que vous cherchez:
1) Étendre la classe List - et y ajouter la méthode join. La méthode join ferait simplement le travail de concaténation et d'ajout du délimiteur (qui pourrait être un paramètre de la méthode join)
2) Il semble que Java 7 va ajouter des méthodes d'extension à java - ce qui vous permet simplement d'attacher une méthode spécifique à une classe: vous pouvez donc écrire cette méthode de jointure et l'ajouter en tant que méthode d'extension à List ou même à Collection.
La solution 1 est probablement la seule réaliste à l'heure actuelle, bien que Java 7 ne soit pas encore sorti :) Mais cela devrait très bien fonctionner.
Pour utiliser les deux, il vous suffit d'ajouter tous vos éléments à la liste ou à la collection comme d'habitude, puis d'appeler la nouvelle méthode personnalisée pour les «joindre».
la source