Java: fonction pour les tableaux comme join () de PHP?

259

Je veux rejoindre un String[]avec une chaîne de colle. Y a-t-il une fonction pour cela?

Nick Heiner
la source
7
Java 8 dispose de cette fonctionnalité prête à l'emploi. Je recommande au lecteur de faire défiler jusqu'à la réponse de @Marek Gregor (et de voter dessus ..)
Stav

Réponses:

307

À partir de Java8, il est possible d'utiliser String.join().

String.join(", ", new String[]{"Hello", "World", "!"})

Génère:

Hello, World, !

Sinon, Apache Commons Lang a une StringUtilsclasse qui a une joinfonction qui réunira les tableaux pour faire un String.

Par exemple:

StringUtils.join(new String[] {"Hello", "World", "!"}, ", ")

Génère les éléments suivants String:

Hello, World, !
coobird
la source
7
Pour le bénéfice des personnes recherchant cette réponse, il convient probablement de noter qu'il s'agit également de l'équivalent d'une jointure Perl.
k-den
3
ça dit que c'est indéfini pour moi
Ninjaxor
@Ninjaxor 1. le pot commons-lang * doit être dans classpath 2. import org.apache.commons.lang3.StringUtils;
peterh
9
Je vous recommande de modifier cette réponse pour ajouter une référence à la nouvelle String.join()méthode introduite dans Java 8. De cette façon, le grand nombre de personnes lisant cette réponse acceptée bénéficiera de cette connaissance. Actuellement, la réponse la plus votée mentionnant ce fait est plutôt perdue ci-dessous ...
Duncan Jones
1
Il convient de mentionner que cela String.join()ne fonctionnerait que pour les éléments List<CharSequence>ou CharSequence[].
Enigo
71

Si vous cherchiez quoi utiliser dans Android, c'est:

String android.text.TextUtils.join(CharSequence delimiter, Object[] tokens)

par exemple:

String joined = TextUtils.join(";", MyStringArray);
Noé
la source
2
C'est clairement la meilleure réponse pour toutes les versions d'Android, car Java 8 ne sort que sur Android dans un instant. Cette solution utilise les bibliothèques Android intégrées, plutôt que ces solutions stupides «inclure une énorme bibliothèque pour effectuer une seule action».
LukeStoneHm
Nous sommes en septembre 2017, Java 8 pour Android est encore loin. Merci pour cette réponse!
Aenadon,
53

Vous pouvez facilement écrire une telle fonction dans une dizaine de lignes de code:

String combine(String[] s, String glue)
{
  int k = s.length;
  if ( k == 0 )
  {
    return null;
  }
  StringBuilder out = new StringBuilder();
  out.append( s[0] );
  for ( int x=1; x < k; ++x )
  {
    out.append(glue).append(s[x]);
  }
  return out.toString();
}
Geai
la source
35
Bonne pratique selon vous ... il n'y a pas de norme universelle pour de telles choses.
phoebus
24
Mais si j'avais inclus des accolades, cela aurait ajouté deux lignes de code supplémentaires, et je n'aurais pas pu prétendre l'avoir fait en 11 lignes!
Jay
8
le problème est quand vous après un certain temps, ou quelqu'un d'autre, pressé, ajoutez une autre ligne à cela si / pour sans ajouter d'accolades; ou supprimer return null après if (k == 0), qui dans certains cas se compile mais sera incorrect. Ensuite, il est préférable de sacrifier une ligne supplémentaire pour cette accolade de fermeture (l'ouverture peut rester dans la même ligne if / for).
mil
16
Je pense que c'est génial que si la plupart des langages intègrent de telles fonctionnalités dans leur cœur, la communauté Java encourage tout le monde à réinventer la roue.
John Strickler
33
11 lignes? Bah! Je peux le faire en 1! Supprimez simplement tous les caractères de nouvelle ligne dans le fichier source.
Thomas Eding
25

Un petit mod au lieu d'utiliser substring ():

//join(String array,delimiter)
public static String join(String r[],String d)
{
        if (r.length == 0) return "";
        StringBuilder sb = new StringBuilder();
        int i;
        for(i=0;i<r.length-1;i++){
            sb.append(r[i]);
            sb.append(d);
        }
        sb.append(r[i]);
        return sb.toString();
}
everlasto
la source
A voté parce que vous n'avez pas besoin d'ajouter de bibliothèque.
givanse
10
Ligne 7: est-il préférable de les utiliser .append()deux fois pour chacun Stringau lieu de les concaténer puis de les ajouter au générateur.
Talha Ahmed Khan
18

Comme pour de nombreuses questions ces derniers temps, Java 8 à la rescousse:


Java 8 a ajouté une nouvelle méthode statique java.lang.Stringqui fait exactement ce que vous voulez:

public static String join(CharSequence delimeter, CharSequence... elements);

En l'utilisant:

String s = String.join(", ", new String[] {"Hello", "World", "!"});

Résulte en:

"Hello, World, !"
icza
la source
14

La bibliothèque de Google goyave a également ce genre de capacité . Vous pouvez également voir l'exemple String [] dans l'API.

Comme déjà décrit dans l'API, méfiez-vous de l'immuabilité des méthodes de construction.

Il peut accepter un tableau d'objets afin que cela fonctionne dans votre cas. Dans mon expérience précédente, j'ai essayé de rejoindre une pile qui est un itérable et cela fonctionne très bien.

Échantillon de moi:

Deque<String> nameStack = new ArrayDeque<>();
nameStack.push("a coder");
nameStack.push("i am");
System.out.println("|" + Joiner.on(' ').skipNulls().join(nameStack) + "|");

imprime: |i am a coder|

Bertie
la source
9

Donné:

String[] a = new String[] { "Hello", "World", "!" };

Ensuite, comme alternative à la réponse de coobird, où la colle est ",":

Arrays.asList(a).toString().replaceAll("^\\[|\\]$", "")

Ou pour concaténer avec une chaîne différente, telle que "& amp;".

Arrays.asList(a).toString().replaceAll(", ", " &amp; ").replaceAll("^\\[|\\]$", "")

Cependant ... celui-ci fonctionne UNIQUEMENT si vous savez que les valeurs du tableau ou de la liste NE contiennent PAS la chaîne de caractères ",".

Rob chez TVSeries.com
la source
Arrays.asList(a).toString()travaillé pour ce que je voulais faire
Solomon Ucko
9

Si vous utilisez Spring Framework, vous disposez de la classe StringUtils :

import static org.springframework.util.StringUtils.arrayToDelimitedString;

arrayToDelimitedString(new String[] {"A", "B", "C"}, "\n");
devstopfix
la source
8

Pas dans le noyau, non. Une recherche de "colle de chaîne de jonction de tableau java" vous donnera quelques extraits de code sur la façon d'y parvenir.

par exemple

public static String join(Collection s, String delimiter) {
    StringBuffer buffer = new StringBuffer();
    Iterator iter = s.iterator();
    while (iter.hasNext()) {
        buffer.append(iter.next());
        if (iter.hasNext()) {
            buffer.append(delimiter);
        }
    }
    return buffer.toString();
}

la source
2
Utilisez StringBuilder (non thread-safe) à la place de StringBuffer (thread-safe) pour de meilleures performances. L'interface est la même.
Asaph
2
Cela semble provenir de snippets.dzone.com/posts/show/91 . Les commentaires suggèrent une version bien améliorée: jointure de chaîne statique publique (Iterable <? Étend l'objet> pColl, séparateur de chaîne) {Iterator <? étend Object> oIter; if (pColl == null || (! (oIter = pColl.iterator ()) .hasNext ())) return ""; StringBuilder oBuilder = nouveau StringBuilder (String.valueOf (oIter.next ())); while (oIter.hasNext ()) oBuilder.append (séparateur) .append (oIter.next ()); return oBuilder.toString (); }
Quantum7
6

Si vous avez atterri ici à la recherche d'une conversion rapide de tableau en chaîne, essayez Arrays.toString () .

Crée une représentation String du Object[]passé. Le résultat est entouré de crochets ( "[]"), chaque élément est converti en une chaîne via le String.valueOf(Object)et séparé par ", ". Si le tableau l'est null, alors "null"est retourné.

menthe douce
la source
MERCI BEAUCOUP! Les cordes sont séparées par "," et le tout a "[]" autour, ce qui me convient.
John Henckel,
5

Juste pour le défi "J'ai le plus court" , voici les mines;)

Itératif:

public static String join(String s, Object... a) {
    StringBuilder o = new StringBuilder();
    for (Iterator<Object> i = Arrays.asList(a).iterator(); i.hasNext();)
        o.append(i.next()).append(i.hasNext() ? s : "");
    return o.toString();
}

Récursif:

public static String join(String s, Object... a) {
    return a.length == 0 ? "" : a[0] + (a.length == 1 ? "" : s + join(s, Arrays.copyOfRange(a, 1, a.length)));
}
sp00m
la source
2
La version récursive est élégante. Je vais certainement l'utiliser.
Pete
La version récursive peut être élégante, mais inefficace pour les grands tableaux (" copyOfRange()").
Ogre Psalm33
4

Voilà comment je le fais.

private String join(String[] input, String delimiter)
{
    StringBuilder sb = new StringBuilder();
    for(String value : input)
    {
        sb.append(value);
        sb.append(delimiter);
    }
    int length = sb.length();
    if(length > 0)
    {
        // Remove the extra delimiter
        sb.setLength(length - delimiter.length());
    }
    return sb.toString();
}
Richard Corfield
la source
2

Une alternative similaire

/**
 * @param delimiter 
 * @param inStr
 * @return String
 */
public static String join(String delimiter, String... inStr)
{
    StringBuilder sb = new StringBuilder();
    if (inStr.length > 0)
    {
        sb.append(inStr[0]);
        for (int i = 1; i < inStr.length; i++)
        {
            sb.append(delimiter);                   
            sb.append(inStr[i]);
        }
    }
    return sb.toString();
}
William Simpson
la source
2

Mon tour.

public static String join(Object[] objects, String delimiter) {
  if (objects.length == 0) {
    return "";
  }
  int capacityGuess = (objects.length * objects[0].toString().length())
      + ((objects.length - 1) * delimiter.length());
  StringBuilder ret = new StringBuilder(capacityGuess);
  ret.append(objects[0]);
  for (int i = 1; i < objects.length; i++) {
    ret.append(delimiter);
    ret.append(objects[i]);
  }
  return ret.toString();
}

public static String join(Object... objects) {
  return join(objects, "");
}
Jackson
la source
1

Aimez-vous ma façon de 3 lignes en utilisant uniquement les méthodes de la classe String?

static String join(String glue, String[] array) {
    String line = "";
    for (String s : array) line += s + glue;
    return (array.length == 0) ? line : line.substring(0, line.length() - glue.length());
}
Ryoichiro Oka
la source
1
Ce n'est pas censé être efficace. À utiliser StringBuildersi vous avez besoin d'efficacité: P
Ryoichiro Oka
0

Pour obtenir "str1, str2" à partir de "str1", "str2", "":

Stream.of("str1", "str2", "").filter(str -> !str.isEmpty()).collect(Collectors.joining(", ")); 

Vous pouvez également ajouter un contrôle nul supplémentaire

ema
la source
0

Dans le cas où vous utilisez la bibliothèque Java fonctionnelle et pour une raison quelconque, vous ne pouvez pas utiliser les flux de Java 8 (ce qui pourrait être le cas lorsque vous utilisez le plug-in Android + Retrolambda), voici une solution fonctionnelle pour vous:

String joinWithSeparator(List<String> items, String separator) {
    return items
            .bind(id -> list(separator, id))
            .drop(1)
            .foldLeft(
                    (result, item) -> result + item,
                    ""
            );
}

Notez que ce n'est pas l'approche la plus efficace, mais cela fonctionne bien pour les petites listes.

Dmitry Zaytsev
la source
-1

Je le fais de cette façon en utilisant un StringBuilder:

public static String join(String[] source, String delimiter) {
    if ((null == source) || (source.length < 1)) {
        return "";
    }

    StringBuilder stringbuilder = new StringBuilder();
    for (String s : source) {
        stringbuilder.append(s + delimiter);
    }
    return stringbuilder.toString();
} // join((String[], String)
spanky762
la source
1
s + delimiter(concaténation de chaînes avec l'opérateur plus) annule tout le but de l'utilisation de a StringBuilder.
quietmint
De plus, cette approche signifierait qu'un tableau comme: {"foo", "bar"} avec délimiteur ":" serait transformé en "foo: bar:"
pioto
-2

Il existe une technique de raccourci simple que j'utilise la plupart du temps.

String op = new String;
for (int i : is) 
{
    op += candidatesArr[i-1]+",";
}
op = op.substring(0, op.length()-1);
Gaurav Adurkar
la source
Cela ne fonctionne qu'avec des délimiteurs de longueur 1 et nécessite des «nombres magiques» (bien que très locaux) si vous vouliez un délimiteur de longueur différente.
maiwald
Vous pouvez ajouter plusieurs caractères lors de l'ajout
Gaurav Adurkar
que simplement faire: op = op.substring (0, op.length () - ",". length ()); quel est le gros problème?
Dennis
-3

java.util.Arrays a une méthode 'asList'. Avec l'API java.util.List / ArrayList, cela vous donne tout ce dont vous avez besoin :;

private static String[] join(String[] array1, String[] array2) {

    List<String> list = new ArrayList<String>(Arrays.asList(array1));
    list.addAll(Arrays.asList(array2));
    return list.toArray(new String[0]);
}
Adriaan Koster
la source
7
La question est de savoir comment joindre un tableau de chaînes avec un délimiteur, et non pas comment joindre deux tableaux de chaînes ensemble.
toolbear