Je cherche une méthode pour combiner un tableau de chaînes en une chaîne délimitée Un opposé à scinder ().
Je voulais demander au forum avant d’essayer d’écrire le mien (le JDK a tout)
Je ne suis au courant d'aucune méthode dans le JDK pour cela. Apache Commons Lang a plusieurs méthodes join()
surchargées dans la classe StringUtils
qui font ce que vous voulez.
Il y a eu une demande de fonctionnalité ouverte depuis au moins 2009. Depuis longtemps, cela fait partie des fonctionnalités de la classe Java.util.StringJoiner du JDK 8. http://download.Java.net/lambda/b81/docs/api/Java/util/StringJoiner.html
Voici le problème Oracle si vous êtes intéressé . http://bugs.Sun.com/view_bug.do?bug_id=5015163
Voici un exemple du nouveau JDK 8 StringJoiner sur un tableau de String
String[] a = new String[]{"first","second","third"};
StringJoiner sj = new StringJoiner(",");
for(String s:a) sj.add(s);
System.out.println(sj); //first,second,third
Une méthode utilitaire dans String rend cela encore plus simple:
String s = String.join(",", stringArray);
Vous pouvez extraire cette fonctionnalité du package Arrays
.
import Java.util.Arrays;
...
String delim = ":",
csv_record = "Field0:Field1:Field2",
fields[] = csv_record.split(delim);
String rebuilt_record = Arrays.toString(fields).replace(", ", delim).replaceAll("[\\[\\]]", "");
J'ai eu l'exemple suivant ici
/*
7) Join Strings using separator >>>AB$#$CD$#$EF
*/
import org.Apache.commons.lang.StringUtils;
public class StringUtilsTrial {
public static void main(String[] args) {
// Join all Strings in the Array into a Single String, separated by $#$
System.out.println("7) Join Strings using separator >>>"
+ StringUtils.join(new String[] { "AB", "CD", "EF" }, "$#$"));
}
}
Google fournit également une classe de menuisier dans sa bibliothèque Google Collections:
Il existe plusieurs exemples sur DZone Snippets si vous souhaitez créer votre propre fichier qui fonctionne avec une collection. Par exemple:
public static String join(AbstractCollection<String> s, String delimiter) {
if (s == null || s.isEmpty()) return "";
Iterator<String> iter = s.iterator();
StringBuilder builder = new StringBuilder(iter.next());
while( iter.hasNext() )
{
builder.append(delimiter).append(iter.next());
}
return builder.toString();
}
Si vous avez un int [], Arrays.toString()
est le moyen le plus simple.
Basé sur toutes les réponses précédentes:
public static String join(Iterable<? extends Object> elements, CharSequence separator)
{
StringBuilder builder = new StringBuilder();
if (elements != null)
{
Iterator<? extends Object> iter = elements.iterator();
if(iter.hasNext())
{
builder.append( String.valueOf( iter.next() ) );
while(iter.hasNext())
{
builder
.append( separator )
.append( String.valueOf( iter.next() ) );
}
}
}
return builder.toString();
}
Pour Android: in Android.text.TextUtils Il existe des méthodes:
public static String join (CharSequence delimiter, Iterable tokens)
public static String join (CharSequence delimiter, Object[] tokens)
Retourne une chaîne contenant les jetons joints par des délimiteurs.
tokens - objets de tableau à joindre. Les chaînes seront formées à partir des objets en appelant object.toString ().
Celui-ci n'est pas mal aussi:
public static String join(String delimitor,String ... subkeys) {
String result = null;
if(null!=subkeys && subkeys.length>0) {
StringBuffer joinBuffer = new StringBuffer(subkeys[0]);
for(int idx=1;idx<subkeys.length;idx++) {
joinBuffer.append(delimitor).append(subkeys[idx]);
}
result = joinBuffer.toString();
}
return result;
}
Depuis JDK8, j'aime beaucoup Streams et Lambdas, je vous suggère donc:
public static String join( String delimiter, String[] array )
{
return Arrays.asList( array ).stream().collect( Collectors.joining( delimiter ) );
}
Par souci d’exhaustivité, je voudrais ajouter que vous ne pouvez pas inverser String # split en général, car il accepte une expression régulière.
"hello__world".split("_+");
Rend ["hello", "world"]
."hello_world".split("_+");
Rend ["hello", "world"]
.
Ceux-ci donnent des résultats identiques à partir d'un point de départ différent. le fractionnement n'est pas une opération un par un, il est donc irréversible.
Tout cela étant dit, si vous supposez que votre paramètre est une chaîne fixe, pas une regex, vous pouvez certainement le faire en utilisant l’une des nombreuses réponses publiées.
J'ai écrit celui-ci:
public static String join(Collection<String> col, String delim) {
StringBuilder sb = new StringBuilder();
Iterator<String> iter = col.iterator();
if (iter.hasNext())
sb.append(iter.next());
while (iter.hasNext()) {
sb.append(delim);
sb.append(iter.next());
}
return sb.toString();
}
Collection
n'est pas supporté par JSP, donc pour TLD j'ai écrit:
public static String join(List<?> list, String delim) {
int len = list.size();
if (len == 0)
return "";
StringBuilder sb = new StringBuilder(list.get(0).toString());
for (int i = 1; i < len; i++) {
sb.append(delim);
sb.append(list.get(i).toString());
}
return sb.toString();
}
et mettre dans le fichier .tld
:
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://Java.Sun.com/xml/ns/javaee"
<function>
<name>join</name>
<function-class>com.core.util.ReportUtil</function-class>
<function-signature>Java.lang.String join(Java.util.List, Java.lang.String)</function-signature>
</function>
</taglib>
et l'utiliser dans les fichiers JSP en tant que:
<%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%>
${funnyFmt:join(books, ", ")}
Le code ci-dessous donne une idée de base. Ce n'est pas la meilleure solution cependant.
public static String splitJoin(String sourceStr, String delim,boolean trim,boolean ignoreEmpty){
return join(Arrays.asList(sourceStr.split(delim)), delim, ignoreEmpty);
}
public static String join(List<?> list, String delim, boolean ignoreEmpty) {
int len = list.size();
if (len == 0)
return "";
StringBuilder sb = new StringBuilder(list.get(0).toString());
for (int i = 1; i < len; i++) {
if (ignoreEmpty && !StringUtils.isBlank(list.get(i).toString())) {
sb.append(delim);
sb.append(list.get(i).toString().trim());
}
}
return sb.toString();
}
J'aime mieux ça:
public String join(Collection<String> strCollection, String delimiter) {
String joined = "";
int noOfItems = 0;
for (String item : strCollection) {
joined += item;
if (++noOfItems < strCollection.size())
joined += delimiter;
}
return joined;
}
C’est la solution la plus soignée que j’ai trouvée jusqu’à présent… .. (ne vous inquiétez pas de l’utilisation d’objets String bruts au lieu de StringBuilder. Les compilateurs Java modernes utilisent quand même StringBuilder, mais ce code est plus lisible).
Si vous utilisez jdk8, voyez answer de @Nathaniel Johnson car c'est mieux.
Je pense que beaucoup de réponses ici sont complexes ou difficiles à lire. Avec la prédiction de branche si efficace, pourquoi ne pas simplement utiliser une instruction if?
public static String join(List<String> fooList){
if (fooList.isEmpty()) return "";
StringBuilder sb = null;
for (String element : fooList) {
if (sb == null) {
sb = new StringBuilder();
} else {
sb.append(", ");
}
sb.append(element);
}
return sb.toString();
}
Il convient de mentionner qu'Apache utilise une boucle for simple avec une instruction if comme ceci (elle utilise un tableau comme index pour connaître le premier élément), et openjdk 8 fait de même, mais dans des méthodes séparées, des appels à la place d'un boucle simple.