web-dev-qa-db-fra.com

Un moyen rapide et facile de joindre des éléments de tableau avec un séparateur (l'opposé de split) dans Java

Voir Question .NET associée

Je cherche un moyen rapide et facile de faire exactement le contraire de split pour que ["a","b","c"] devienne "a,b,c"

Pour itérer dans un tableau, vous devez soit ajouter une condition (si ce n'est pas le dernier élément, ajoutez le séparateur), soit utiliser une sous-chaîne pour supprimer le dernier séparateur.

Je suis sûr qu'il existe un moyen certifié et efficace de le faire (Apache Commons?)

Comment préférez-vous le faire dans vos projets?

422
Eran Medan

En utilisant Java 8, vous pouvez le faire de manière très propre:

String.join(delimiter, elements);

Cela fonctionne de trois manières:

1) spécifiant directement les éléments

String joined1 = String.join(",", "a", "b", "c");

2) en utilisant des tableaux

String[] array = new String[] { "a", "b", "c" };
String joined2 = String.join(",", array);

3) en utilisant iterables

List<String> list = Arrays.asList(array);
String joined3 = String.join(",", list);
676
skiwi

Si vous êtes sur Android, vous pouvez TextUtils.join(delimiter, tokens)

283
nmr

Je préfère Google Collections à Apache StringUtils pour ce problème particulier:

Joiner.on(separator).join(array)

Comparée à StringUtils, l’API Joiner a une conception fluide et est un peu plus flexible, par exemple. Les éléments null peuvent être ignorés ou remplacés par un espace réservé. De plus, Joiner dispose d'une fonctionnalité permettant de joindre des cartes avec un séparateur entre clé et valeur.

113
nd.

Apache Commons Lang possède en effet une méthode StringUtils.join qui connectera les tableaux String avec un séparateur spécifié.

Par exemple:

_String[] s = new String[] {"a", "b", "c"};
String joined = StringUtils.join(s, ",");  // "a,b,c"
_

Cependant, je soupçonne que, comme vous l'avez mentionné, la mise en œuvre effective de la méthode susmentionnée doit comporter un type de traitement conditionnel ou de sous-chaîne.

Si je devais effectuer la jonction String et que je n'avais aucune autre raison d'utiliser Commons Lang, je roulerais probablement moi-même pour réduire le nombre de dépendances vers des bibliothèques externes.

104
coobird

Une solution simple et rapide sans aucun tiers comprend.

public static String strJoin(String[] aArr, String sSep) {
    StringBuilder sbStr = new StringBuilder();
    for (int i = 0, il = aArr.length; i < il; i++) {
        if (i > 0)
            sbStr.append(sSep);
        sbStr.append(aArr[i]);
    }
    return sbStr.toString();
}
44
Zedas

"Je suis sûr qu'il existe un moyen certifié et efficace de le faire (Apache Commons?)"

oui, apparemment c'est

StringUtils.join(array, separator)

http://www.Java2s.com/Code/JavaAPI/org.Apache.commons.lang/StringUtilsjoinObjectarrayStringseparator.htm

23
Roland Bouman

Avec Java 1.8, il existe un nouveau StringJoiner class - il n'est donc pas nécessaire d'utiliser Guava ou Apache Commons:

String str = new StringJoiner(",").add("a").add("b").add("c").toString();

Ou en utilisant une collection directement avec la nouvelle api de flux:

String str = Arrays.asList("a", "b", "c").stream().collect(Collectors.joining(","));
18
eivindw

Encore plus facilement, vous pouvez simplement utiliser des tableaux, de sorte que vous obtiendrez une chaîne avec les valeurs du tableau séparées par un ","

String concat = Arrays.toString(myArray);

donc vous allez vous retrouver avec ceci: concat = "[a, b, c]"

Mise à jour

Vous pouvez ensuite vous débarrasser des crochets en utilisant une sous-chaîne comme suggéré par Jeff

concat = concat.substring(1, concat.length() -1);

donc vous vous retrouvez avec concat = "a, b, c"

17
alexm

Vous pouvez utiliser replace et replaceAll avec des expressions régulières.

String[] strings = {"a", "b", "c"};

String result = Arrays.asList(strings).toString().replaceAll("(^\\[|\\]$)", "").replace(", ", ",");

Étant donné que Arrays.asList().toString() produit: "[a, b, c]", nous faisons un replaceAll pour supprimer les premier et dernier crochets, puis (éventuellement) vous pouvez modifier le "," séquence pour "," (votre nouveau séparateur).

Une version stripped (moins de caractères):

String[] strings = {"a", "b", "c"};

String result = ("" + Arrays.asList(strings)).replaceAll("(^.|.$)", "").replace(", ", "," );

Les expressions régulières sont très puissantes, en particulier les méthodes String "replaceFirst" et "replaceAll". Donnez-leur un essai.

16
wadjakman

Toutes ces autres réponses incluent une surcharge d'exécution ... comme l'utilisation de ArrayList.toString (). ReplaceAll (...) qui sont très inutiles.

Je vais vous donner l'algorithme optimal avec zéro overhead; cela ne semble pas aussi joli que les autres options, mais en interne, c'est ce qu'elles sont toutes en train de faire (après des piles d'autres contrôles cachés, une allocation de plusieurs tableaux et d'autres choses crud).

Comme vous savez déjà que vous traitez avec des chaînes, vous pouvez enregistrer un tas d'allocations de tableaux en effectuant tout manuellement. Cela n’est pas beau, mais si vous tracez les appels de méthode effectués par les autres implémentations, vous constaterez que le temps système d’exécution est le moins lourd possible.

public static String join(String separator, String ... values) {
  if (values.length==0)return "";//need at least one element
  //all string operations use a new array, so minimize all calls possible
  char[] sep = separator.toCharArray();

  // determine final size and normalize nulls
  int totalSize = (values.length - 1) * sep.length;// separator size
  for (int i = 0; i < values.length; i++) {
    if (values[i] == null)
      values[i] = "";
    else
      totalSize += values[i].length();
  }

  //exact size; no bounds checks or resizes
  char[] joined = new char[totalSize];
  int pos = 0;
  //note, we are iterating all the elements except the last one
  for (int i = 0, end = values.length-1; i < end; i++) {
    System.arraycopy(values[i].toCharArray(), 0, 
      joined, pos, values[i].length());
    pos += values[i].length();
    System.arraycopy(sep, 0, joined, pos, sep.length);
    pos += sep.length;
  }
  //now, add the last element; 
  //this is why we checked values.length == 0 off the hop
  System.arraycopy(values[values.length-1].toCharArray(), 0,
    joined, pos, values[values.length-1].length());

  return new String(joined);
}
8
Ajax
6
David Hedlund

Cette option est rapide et claire:

  public static String join(String separator, String... values) {
    StringBuilder sb = new StringBuilder(128);
    int end = 0;
    for (String s : values) {
      if (s != null) {
        sb.append(s);
        end = sb.length();
        sb.append(separator);
      }
    }
    return sb.substring(0, end);
  }
6
mnesarco

Cette petite fonction est toujours pratique.

public static String join(String[] strings, int startIndex, String separator) {
    StringBuffer sb = new StringBuffer();
    for (int i=startIndex; i < strings.length; i++) {
        if (i != startIndex) sb.append(separator);
        sb.append(strings[i]);
    }
    return sb.toString();
}
4
SSpoke

L’approche que j’ai adoptée a évolué depuis Java 1.0 afin de garantir la lisibilité et de conserver des options raisonnables en matière de rétrocompatibilité avec les versions antérieures Java, tout en fournissant des signatures de méthode qui se font de manière autonome. remplacements pour ceux d’Apache commons-lang. Pour des raisons de performances, je peux voir quelques objections possibles à l’utilisation de Arrays.asList mais je préfère les méthodes auxiliaires qui ont des valeurs par défaut raisonnables sans dupliquer la méthode qui effectue le travail réel. Cette approche fournit des points d'entrée appropriés à une méthode fiable qui n'exige pas de conversions de tableaux/listes avant d'appeler.

Les variantes possibles pour la compatibilité de la version de Java incluent la substitution de StringBuffer (Java 1.0) à StringBuilder (Java 1.5), la suppression de l'itérateur Java 1.5 et la suppression du caractère générique (Java 1.5) de la collection. (Java 1.2). Si vous souhaitez passer à la compatibilité ascendante une ou deux étapes plus loin, supprimez les méthodes qui utilisent Collection et déplacez la logique dans la méthode basée sur un tableau.

public static String join(String[] values)
{
    return join(values, ',');
}

public static String join(String[] values, char delimiter)
{
    return join(Arrays.asList(values), String.valueOf(delimiter));
}

// To match Apache commons-lang: StringUtils.join(values, delimiter)
public static String join(String[] values, String delimiter)
{
    return join(Arrays.asList(values), delimiter);
}

public static String join(Collection<?> values)
{
    return join(values, ',');
}

public static String join(Collection<?> values, char delimiter)
{
    return join(values, String.valueOf(delimiter));
}

public static String join(Collection<?> values, String delimiter)
{
    if (values == null)
    {
        return new String();
    }

    StringBuffer strbuf = new StringBuffer();

    boolean first = true;

    for (Object value : values)
    {
        if (!first) { strbuf.append(delimiter); } else { first = false; }
        strbuf.append(value.toString());
    }

    return strbuf.toString();
}
3
vallismortis
public String join(String[] str, String separator){
    String retval = "";
    for (String s: str){ retval+= separator + s;}
    return retval.replaceFirst(separator, "");
}
1
IvanP