web-dev-qa-db-fra.com

Java: convertir la liste <String> en chaîne

JavaScript a Array.join()

js>["Bill","Bob","Steve"].join(" and ")
Bill and Bob and Steve

Est-ce que Java a quelque chose comme ça? Je sais que je peux bricoler quelque chose avec StringBuilder:

static public String join(List<String> list, String conjunction)
{
   StringBuilder sb = new StringBuilder();
   boolean first = true;
   for (String item : list)
   {
      if (first)
         first = false;
      else
         sb.append(conjunction);
      sb.append(item);
   }
   return sb.toString();
}

... mais cela ne sert à rien de faire cela si quelque chose du genre fait déjà partie du JDK.

533
Jason S

Avec Java 8, vous pouvez le faire sans aucune bibliothèque tierce.

Si vous souhaitez rejoindre une collection de chaînes, vous pouvez utiliser la nouvelle méthode String.join () :

List<String> list = Arrays.asList("foo", "bar", "baz");
String joined = String.join(" and ", list); // "foo and bar and baz"

Si vous avez une collection avec un autre type que String, vous pouvez utiliser l'API Stream avec le join Collector :

List<Person> list = Arrays.asList(
  new Person("John", "Smith"),
  new Person("Anna", "Martinez"),
  new Person("Paul", "Watson ")
);

String joinedFirstNames = list.stream()
  .map(Person::getFirstName)
  .collect(Collectors.joining(", ")); // "John, Anna, Paul"

La classe StringJoiner peut également être utile.

670
micha

Toutes les références à Apache Commons sont correctes (et c'est ce que la plupart des gens utilisent), mais je pense que le Guava équivalent, Joiner , possède une API beaucoup plus agréable.

Vous pouvez faire le cas simple rejoindre avec

Joiner.on(" and ").join(names)

mais aussi facilement traiter avec nulls:

Joiner.on(" and ").skipNulls().join(names);

ou

Joiner.on(" and ").useForNull("[unknown]").join(names);

et (assez utile en ce qui me concerne pour l’utiliser de préférence à commons-lang), la capacité de traiter avec Maps:

Map<String, Integer> ages = .....;
String foo = Joiner.on(", ").withKeyValueSeparator(" is ").join(ages);
// Outputs:
// Bill is 25, Joe is 30, Betty is 35

ce qui est extrêmement utile pour le débogage, etc.

300
Cowan

Non prêt à l'emploi, mais de nombreuses bibliothèques ont les mêmes:

Commons Lang:

org.Apache.commons.lang.StringUtils.join(list, conjunction);

Printemps:

org.springframework.util.StringUtils.collectionToDelimitedString(list, conjunction);
135
Arne Burmeister

Sur Android, vous pouvez utiliser la classe TextUtils.

TextUtils.join(" and ", names);
118
Rafal Enden

Non, l'API Java standard ne contient pas cette méthode pratique.

Sans surprise, Apache Commons fournit une telle chose dans leur classe StringUtils au cas où vous ne voudriez pas l'écrire vous-même.

49
Bart Kiers

Trois possibilités en Java 8:

List<String> list = Arrays.asList("Alice", "Bob", "Charlie")

String result = String.join(" and ", list);

result = list.stream().collect(Collectors.joining(" and "));

result = list.stream().reduce((t, u) -> t + " and " + u).orElse("");
37
amra

Avec un collecteur Java 8, cela peut être fait avec le code suivant:

Arrays.asList("Bill", "Bob", "Steve").stream()
.collect(Collectors.joining(" and "));

Aussi, la solution la plus simple de Java 8:

String.join(" and ", "Bill", "Bob", "Steve");

ou

String.join(" and ", Arrays.asList("Bill", "Bob", "Steve"));
25
aifa

J'ai écrit celui-ci (je l'utilise pour les beans et exploite toString, alors n'écrivez pas Collection<String>):

public static String join(Collection<?> col, String delim) {
    StringBuilder sb = new StringBuilder();
    Iterator<?> iter = col.iterator();
    if (iter.hasNext())
        sb.append(iter.next().toString());
    while (iter.hasNext()) {
        sb.append(delim);
        sb.append(iter.next().toString());
    }
    return sb.toString();
}

mais Collection n'est pas pris en charge par JSP, c'est pourquoi j'ai écrit pour TLD:

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

Le code que vous avez est la bonne façon de le faire si vous voulez utiliser JDK sans aucune bibliothèque externe. Il n'y a pas de simple "one-liner" que vous puissiez utiliser dans JDK.

Si vous pouvez utiliser des bibliothèques externes, je vous recommande de consulter la classe org.Apache.commons.lang.StringUtils de la bibliothèque Apache Commons.

Un exemple d'utilisation:

List<String> list = Arrays.asList("Bill", "Bob", "Steve");
String joinedResult = StringUtils.join(list, " and ");
19
Juha Syrjälä

Une façon orthodoxe d'y parvenir consiste à définir une nouvelle fonction:

public static String join(String join, String... strings) {
    if (strings == null || strings.length == 0) {
        return "";
    } else if (strings.length == 1) {
        return strings[0];
    } else {
        StringBuilder sb = new StringBuilder();
        sb.append(strings[0]);
        for (int i = 1; i < strings.length; i++) {
            sb.append(join).append(strings[i]);
        }
        return sb.toString();
    }
}

Échantillon:

String[] array = new String[] { "7, 7, 7", "Bill", "Bob", "Steve",
        "[Bill]", "1,2,3", "Apple ][","~,~" };

String joined;
joined = join(" and ","7, 7, 7", "Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][","~,~");
joined = join(" and ", array); // same result

System.out.println(joined);

Sortie:

7, 7, 7 et Bill and Bob et Steve et [Bill] et 1,2,3 et Apple] [et ~, ~

16
Daniel De León

Vous pouvez utiliser la bibliothèque Apache commons qui a une classe StringUtils et une méthode de jointure.

Vérifiez ce lien: https://commons.Apache.org/proper/commons-lang/javadocs/api.2.0/org/Apache/commons/lang/StringUtils.html

Notez que le lien ci-dessus peut devenir obsolète au fil du temps. Dans ce cas, vous pouvez simplement rechercher sur le Web "Apache commons StringUtils", ce qui devrait vous permettre de rechercher la dernière référence.

(référencé à partir de ce fil) équivalents Java de C # String.Format () et String.Join ()

9
dcp

Solution Java 8 avec Java.util.StringJoiner

Java 8 a une classe StringJoiner . Mais vous devez toujours écrire un peu de passe-partout, parce que c'est Java.

StringJoiner sj = new StringJoiner(" and ", "" , "");
String[] names = {"Bill", "Bob", "Steve"};
for (String name : names) {
   sj.add(name);
}
System.out.println(sj);
9
klingt.net

Tu peux le faire:

String aToString = Java.util.Arrays.toString(anArray);
// Do not need to do this if you are OK with '[' and ']'
aToString = aToString.substring(1, aToString.length() - 1);

Ou un one-liner (seulement quand vous ne voulez pas '[' et ']')

String aToString = Java.util.Arrays.toString(anArray).substring(1).replaceAll("\\]$", "");

J'espère que cela t'aides.

7
NawaMan

Une façon amusante de le faire avec JDK pur, en une seule ligne:

String[] array = new String[] { "Bill", "Bob", "Steve","[Bill]","1,2,3","Apple ][" };
String join = " and ";

String joined = Arrays.toString(array).replaceAll(", ", join)
        .replaceAll("(^\\[)|(\\]$)", "");

System.out.println(joined);

Sortie:

Bill et Bob et Steve et [Bill] et 1,2,3 et Apple] [


Une manière pas trop parfaite et pas trop amusante!

String[] array = new String[] { "7, 7, 7","Bill", "Bob", "Steve", "[Bill]",
        "1,2,3", "Apple ][" };
String join = " and ";

for (int i = 0; i < array.length; i++) array[i] = array[i].replaceAll(", ", "~,~");
String joined = Arrays.toString(array).replaceAll(", ", join)
        .replaceAll("(^\\[)|(\\]$)", "").replaceAll("~,~", ", ");

System.out.println(joined);

Sortie:

7, 7, 7 et Bill and Bob et Steve et [Bill] et 1,2,3 et Apple] [

5
Daniel De León

Si vous utilisez Collections Eclipse (anciennement Collections GS ), vous pouvez utiliser la méthode makeString().

List<String> list = Arrays.asList("Bill", "Bob", "Steve");

String string = ListAdapter.adapt(list).makeString(" and ");

Assert.assertEquals("Bill and Bob and Steve", string);

Si vous pouvez convertir votre List en un type de collections Eclipse, vous pouvez vous débarrasser de l'adaptateur.

MutableList<String> list = Lists.mutable.with("Bill", "Bob", "Steve");
String string = list.makeString(" and ");

Si vous voulez juste une chaîne séparée par des virgules, vous pouvez utiliser la version de makeString() qui ne prend aucun paramètre.

Assert.assertEquals(
    "Bill, Bob, Steve", 
    Lists.mutable.with("Bill", "Bob", "Steve").makeString());

Remarque: Je suis un partisan des collections Eclipse.

4
Craig P. Motlin

Vous voudrez peut-être essayer la méthode de jointure Apache Commons StringUtils:

http://commons.Apache.org/lang/api/org/Apache/commons/lang/StringUtils.html#join (Java.util.Iterator , Java.lang.String)

J'ai trouvé Apache StringUtils prendre le relais de jdk ;-)

4
Upgradingdave

L'API Guava de Google a également .join (), bien que (comme cela devrait être évident avec les autres réponses), Apache Commons est à peu près la norme ici.

2
Dean J

EDIT

J'ai également remarqué le problème d'implémentation toString() sous-jacent et de l'élément contenant le séparateur, mais je pensais être paranoïaque.

Depuis que j'ai deux commentaires à ce sujet, je change ma réponse à:

    static String join( List<String> list , String replacement  ) {
        StringBuilder b = new StringBuilder();
        for( String item: list ) { 
            b.append( replacement ).append( item );
        }
        return b.toString().substring( replacement.length() );
    }

Ce qui ressemble assez à la question initiale.

Donc, si vous ne souhaitez pas ajouter le pot entier à votre projet, vous pouvez l'utiliser.

Je pense qu'il n'y a rien de mal avec votre code d'origine. En fait, l’alternative suggérée par tout le monde est presque la même (bien qu’elle fasse un certain nombre de validations supplémentaires)

Le voici, avec le licence Apache 2.0.

public static String join(Iterator iterator, String separator) {
       // handle null, zero and one elements before building a buffer
       if (iterator == null) {
           return null;
       }
       if (!iterator.hasNext()) {
           return EMPTY;
       }
       Object first = iterator.next();
       if (!iterator.hasNext()) {
           return ObjectUtils.toString(first);
       }

       // two or more elements
       StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
       if (first != null) {
           buf.append(first);
       }

       while (iterator.hasNext()) {
           if (separator != null) {
               buf.append(separator);
           }
           Object obj = iterator.next();
           if (obj != null) {
               buf.append(obj);
           }
       }
       return buf.toString();
   }

Maintenant nous savons, merci open source

2
OscarRyz

Avec Java 1.8, le flux peut être utilisé,

import Java.util.Arrays;
import Java.util.List;
import Java.util.stream.Collectors;
List<String> list = Arrays.asList("Bill","Bob","Steve").
String str = list.stream().collect(Collectors.joining(" and "));
2
Saurabh

Java 8 apporte la

Collectors.joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

méthode, qui est nullsafe en utilisant prefix + suffix pour les valeurs null.

Il peut être utilisé de la manière suivante:

String s = stringList.stream().collect(Collectors.joining(" and ", "prefix_", "_suffix"))

La méthode Collectors.joining(CharSequence delimiter) appelle simplement joining(delimiter, "", "") en interne.

1
thg

Vous pouvez utiliser ceci à partir de StringUtils de Spring Framework. Je sais que cela a déjà été mentionné, mais vous pouvez en fait prendre ce code et cela fonctionne immédiatement, sans avoir besoin de Spring.

// from https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/Java/org/springframework/util/StringUtils.Java

/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.Apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
public class StringUtils {
    public static String collectionToDelimitedString(Collection<?> coll, String delim, String prefix, String suffix) {
        if(coll == null || coll.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        Iterator<?> it = coll.iterator();
        while (it.hasNext()) {
            sb.append(prefix).append(it.next()).append(suffix);
            if (it.hasNext()) {
                sb.append(delim);
            }
        }
        return sb.toString();
    }
}
0
EpicPandaForce