web-dev-qa-db-fra.com

Le moyen le plus rapide de mettre le contenu de Set <String> dans une seule chaîne avec des mots séparés par un espace?

J'en ai quelques uns Set<String>s et souhaitez transformer chacun de ces éléments en un seul String où chaque élément du Set d'origine est séparé par un espace "". Une première approche naïve consiste à le faire comme ceci

Set<String> set_1;
Set<String> set_2;

StringBuilder builder = new StringBuilder();
for (String str : set_1) {
  builder.append(str).append(" ");
}

this.string_1 = builder.toString();

builder = new StringBuilder();
for (String str : set_2) {
  builder.append(str).append(" ");
}

this.string_2 = builder.toString();

Quelqu'un peut-il penser à un moyen plus rapide, plus joli ou plus efficace de le faire?

49
Lars Andren

Avec commons/lang, vous pouvez le faire en utilisant StringUtils.join :

String str_1 = StringUtils.join(set_1, " ");

Vous ne pouvez pas vraiment battre cela pour être bref.

Mise à jour:

En relisant cette réponse, je préférerais l'autre réponse concernant Joiner Guava maintenant. En fait, ces jours-ci, je ne m'approche pas des Apaches communs.

Une autre mise à jour:

Java 8 a introduit la méthode String.join()

String joined = String.join(",", set);

Bien que ce ne soit pas aussi flexible que la version Guava, c'est pratique lorsque vous n'avez pas la bibliothèque Guava sur votre chemin de classe.

96
Sean Patrick Floyd

Si vous utilisez Java 8, vous pouvez utiliser le natif

String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)

méthode:

Renvoie un nouveau String composé de copies des éléments CharSequence réunis avec une copie du délimiteur spécifié. Par exemple:

 Set<String> strings = new LinkedHashSet<>();
 strings.add("Java"); strings.add("is");
 strings.add("very"); strings.add("cool");
 String message = String.join("-", strings);
 //message returned is: "Java-is-very-cool"

Set implémente Iterable, utilisez donc simplement:

String.join(" ", set_1);
29
Jasper de Vries

En contrepoint de la réponse commons-lang de Seanizer, si vous utilisez Guava Libraries de Google (que je considérerais comme le `` successeur '' de commons-lang, à bien des égards), vous utiliseriez - Joiner :

Joiner.on(" ").join(set_1);

avec l'avantage de quelques méthodes d'aide pour faire des choses comme:

Joiner.on(" ").skipNulls().join(set_1);
// If 2nd item was null, would produce "1, 3"

ou

Joiner.on(" ").useForNull("<unknown>").join(set_1);
// If 2nd item was null, would produce "1, <unknown>, 3"

Il prend également en charge l'ajout direct aux StringBuilders et Writers, et d'autres subtilités de ce type.

20
Cowan

Je n'ai pas la bibliothèque StringUtil disponible (je n'ai pas le choix), donc en utilisant la norme Java je suis venu avec cela ..

Si vous êtes sûr que vos données ne comprendront pas de virgules ou de crochets, vous pouvez utiliser:

mySet.toString().replaceAll("\\[|\\]","").replaceAll(","," ");

Un ensemble de "a", "b", "c" convertit via .toString () en chaîne "[a, b, c]".

Remplacez ensuite la ponctuation supplémentaire comme nécessaire.

Saleté.

6
user2808054

Peut-être une solution plus courte:

public String test78 (Set<String> set) {
    return set
        .stream()
        .collect(Collectors.joining(" "));
}

ou

public String test77 (Set<String> set) {
    return set
        .stream()
        .reduce("", (a,b)->(a + " " + b));
}

mais natif, nettement plus rapide

public String test76 (Set<String> set) {
    return String.join(" ", set);
}
4
Alexey Rykhalskiy

J'utilise cette méthode:

public static String join(Set<String> set, String sep) {
    String result = null;
    if(set != null) {
        StringBuilder sb = new StringBuilder();
        Iterator<String> it = set.iterator();
        if(it.hasNext()) {
            sb.append(it.next());
        }
        while(it.hasNext()) {
            sb.append(sep).append(it.next());
        }
        result = sb.toString();
    }
    return result;
}
4
tuxdna

Je suis confus au sujet de la réplication de code, pourquoi ne pas la factoriser dans une fonction qui prend un ensemble et renvoie une chaîne?

En dehors de cela, je ne suis pas sûr qu'il y ait beaucoup de choses que vous pouvez faire, sauf peut-être donner au constructeur de chaînes un indice sur la capacité attendue (si vous pouvez la calculer en fonction de la taille définie et d'une attente raisonnable de longueur de chaîne).

Il existe également des fonctions de bibliothèque pour cela, mais je doute qu'elles soient nettement plus efficaces.

2
Uri

Cela peut être fait en créant un flux à partir de l'ensemble, puis en combinant les éléments à l'aide d'une opération de réduction, comme indiqué ci-dessous (pour plus de détails sur Java 8 streams check here ):

Optional<String> joinedString = set1.stream().reduce(new 
BinaryOperator<String>() {

     @Override
     public String apply(String t, String u) {

       return t + " " + u;
    }
});
return joinedString.orElse("");
2
Ehab Qadah