web-dev-qa-db-fra.com

Une méthode pour inverser l'effet de Java String.split ()?

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)

121
javaphild

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.

90
John Topley

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

Mettre à jour

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);
39
Nathaniel Johnson

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("[\\[\\]]", "");
22
David Howard

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" }, "$#$"));
  }
}
16
Azder

Google fournit également une classe de menuisier dans sa bibliothèque Google Collections:

API Joiner

Google Collections

12
Blair Zajac

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();
}
10
Bill the Lizard

Si vous avez un int [], Arrays.toString() est le moyen le plus simple.

7
DenTheMan

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();
}
4
Sarabjot

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 ().

3

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;
}
1
Microscotch

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 ) );
}
1
Radouxca

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.

1
Cruncher

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, ", ")}
1
gavenkoa

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();
}
1
Ashwin Rayaprolu

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).

0
Luis

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.

0
PhoneixS