352 votes

Meilleure façon de convertir une ArrayList en chaîne

J'ai un ArrayList que je veux produire complètement en tant que chaîne. Essentiellement je veux le sortir dans l'ordre en utilisant le toString de chaque élément séparé par des tabulations. Y a-t-il un moyen rapide de le faire? Vous pouvez passer en boucle (ou supprimer chaque élément) et le concaténer à une chaîne mais je pense que ce sera très lent.

1148voto

Vitalii Fedorenko Points 17469

En Java 8 ou plus tard:

 String listString = String.join(", ", list);
 

423voto

jgeewax Points 3026

Si vous faites cela sur Android, il y a un bon utilitaire pour ce TextUtils qui a une méthode .join(String delimiter, Iterable) .

 List<String> list = new ArrayList<String>();
list.add("Item 1");
list.add("Item 2");
String joined = TextUtils.join(", ", list);
 

Évidemment pas beaucoup d'utilisation en dehors d'Android, mais figuré je l'ajouterais à ce fil ...

378voto

coobird Points 70356

Fondamentalement, l'aide d'une boucle pour parcourir l' ArrayList est la seule option:

ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

String listString = "";

for (String s : list)
{
    listString += s + "\t";
}

System.out.println(listString);

En fait, une concaténation de chaîne est va être très bien, comme l' javac compilateur d'optimiser la concaténation de chaîne comme une série d' append des opérations sur un StringBuilder de toute façon. Voici une partie du démontage du bytecode de l' for boucle à partir du programme ci-dessus:

   61:  new #13; //class java/lang/StringBuilder
   64:  dup
   65:  invokespecial   #14; //Method java/lang/StringBuilder."<init>":()V
   68:  aload_2
   69:  invokevirtual   #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   72:  aload   4
   74:  invokevirtual   #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   77:  ldc #16; //String \t
   79:  invokevirtual   #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   82:  invokevirtual   #17; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

Comme on peut le voir, le compilateur optimise en boucle à l'aide d'un StringBuilder, de sorte que les performances ne devraient pas être une grande préoccupation.

(OK, sur le deuxième coup d'œil, l' StringBuilder est instancié à chaque itération de la boucle, de sorte qu'il peut ne pas être le plus efficace du bytecode. L'instanciation et l'utilisation explicite StringBuilder produirait probablement de meilleures performances.)

En fait, je pense que le fait d'avoir toute sorte de sortie (que ce soit sur disque ou sur l'écran) sera d'au moins un ordre de grandeur plus lent que d'avoir à vous soucier de la performance de la chaîne de concaténations.

Edit: Comme l'a souligné dans les commentaires, ci-dessus optimisation du compilateur est en effet la création d'une nouvelle instance de l' StringBuilder à chaque itération. (Que j'ai mentionné précédemment.)

Le plus optimisé la technique à utiliser sera la réponse de Paul Tomblin, car elle ne s'instancie un StringBuilder objet en dehors de l' for boucle.

La réécriture pour le code ci-dessus:

ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

StringBuilder sb = new StringBuilder();
for (String s : list)
{
    sb.append(s);
    sb.append("\t");
}

System.out.println(sb.toString());

Ne instancier l' StringBuilder une fois à l'extérieur de la boucle, et de faire les deux appels à la append méthode à l'intérieur de la boucle, comme en témoigne cette bytecode (qui montre l'instanciation d' StringBuilder , et la boucle):

   // Instantiation of the StringBuilder outside loop:
   33:  new #8; //class java/lang/StringBuilder
   36:  dup
   37:  invokespecial   #9; //Method java/lang/StringBuilder."<init>":()V
   40:  astore_2

   // [snip a few lines for initializing the loop]
   // Loading the StringBuilder inside the loop, then append:
   66:  aload_2
   67:  aload   4
   69:  invokevirtual   #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   72:  pop
   73:  aload_2
   74:  ldc #15; //String \t
   76:  invokevirtual   #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   79:  pop

Donc, en effet la main d'optimisation devrait être plus performants, comme l'intérieur de l' for boucle est plus court et il n'est pas nécessaire d'instancier un StringBuilder à chaque itération.

253voto

Ravi Wallau Points 5012

Téléchargez le Jakarta Commons Lang et utilisez la méthode

  StringUtils.join(list)
 

Vous pouvez l'implémenter vous-même, bien sûr, mais leur code est entièrement testé et est probablement la meilleure implémentation possible.

Je suis un grand fan de la bibliothèque de Jakarta Commons et je pense aussi que c'est un excellent ajout à la Java Standard Library.

140voto

Jon Skeet Points 692016

C'est une question assez ancienne, mais je me dis que je pourrais aussi bien ajouter une réponse plus moderne - utiliser la classe Joiner de Guava :

 String joined = Joiner.on("\t").join(list);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X