Meilleur moyen de convertir une ArrayList en chaîne

J’ai un ArrayList que je veux sortir complètement en tant que chaîne. Essentiellement, je veux le sortir dans l’ordre en utilisant le toSsortingng de chaque élément séparé par des tabulations. Y a-t-il un moyen rapide de le faire? Vous pourriez le parcourir (ou supprimer chaque élément) et le concaténer en une chaîne, mais je pense que cela sera très lent.

Fondamentalement, utiliser une boucle pour parcourir la ArrayList est la seule option possible:

N’utilisez PAS ce code, continuez à lire au bas de cette réponse pour voir pourquoi cela n’est pas souhaitable, et quel code devrait être utilisé à la place:

 ArrayList list = new ArrayList(); list.add("one"); list.add("two"); list.add("three"); Ssortingng listSsortingng = ""; for (Ssortingng s : list) { listSsortingng += s + "\t"; } System.out.println(listSsortingng); 

En fait, une concaténation de chaînes de caractères va très bien se passer, car le compilateur javac optimisera la concaténation de chaînes sous la forme d’une série d’opérations d’ append sur un SsortingngBuilder . Voici une partie du désassemblage du bytecode de la boucle for du programme ci-dessus:

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

Comme on peut le voir, le compilateur optimise cette boucle en utilisant un SsortingngBuilder , donc les performances ne devraient pas être un gros problème.

(OK, au second coup d’œil, SsortingngBuilder est instancié à chaque itération de la boucle, ce qui fait qu’il n’est peut-être pas le bytecode le plus efficace. Instancier et utiliser un SsortingngBuilder explicite donnerait probablement de meilleures performances.)

En fait, je pense que le fait d’avoir une sortie quelconque (que ce soit sur disque ou à l’écran) sera au moins d’un ordre de grandeur plus lent que de se soucier des performances des concaténations de chaînes.

Edit: Comme indiqué dans les commentaires, l’optimisation du compilateur ci-dessus crée en effet une nouvelle instance de SsortingngBuilder à chaque itération. (Ce que j’ai noté précédemment.)

La technique la plus optimisée à utiliser sera la réponse de Paul Tomblin , car elle n’instancie qu’un seul object SsortingngBuilder dehors de la boucle for .

Réécriture du code ci-dessus pour:

 ArrayList list = new ArrayList(); list.add("one"); list.add("two"); list.add("three"); SsortingngBuilder sb = new SsortingngBuilder(); for (Ssortingng s : list) { sb.append(s); sb.append("\t"); } System.out.println(sb.toSsortingng()); 

Instanciera uniquement le SsortingngBuilder une fois en dehors de la boucle, et effectuera uniquement les deux appels à la méthode append à l’intérieur de la boucle, comme en témoigne ce bytecode (qui montre l’instanciation de SsortingngBuilder et de la boucle):

  // Instantiation of the SsortingngBuilder outside loop: 33: new #8; //class java/lang/SsortingngBuilder 36: dup 37: invokespecial #9; //Method java/lang/SsortingngBuilder."":()V 40: astore_2 // [snip a few lines for initializing the loop] // Loading the SsortingngBuilder inside the loop, then append: 66: aload_2 67: aload 4 69: invokevirtual #14; //Method java/lang/SsortingngBuilder.append:(Ljava/lang/Ssortingng;)Ljava/lang/SsortingngBuilder; 72: pop 73: aload_2 74: ldc #15; //Ssortingng \t 76: invokevirtual #14; //Method java/lang/SsortingngBuilder.append:(Ljava/lang/Ssortingng;)Ljava/lang/SsortingngBuilder; 79: pop 

Donc, en fait, l’optimisation de la main devrait être plus performante, car l’intérieur de la boucle for est plus court et il n’est pas nécessaire d’instancier un SsortingngBuilder à chaque itération.

Dans Java 8 ou version ultérieure:

 Ssortingng listSsortingng = Ssortingng.join(", ", list); 

Si la list n’est pas de type Ssortingng, un collecteur de jointure peut être utilisé:

 Ssortingng listSsortingng = list.stream().map(Object::toSsortingng) .collect(Collectors.joining(", ")); 

Si vous faites cela sur Android, il existe un utilitaire intéressant appelé TextUtils qui a une .join(Ssortingng delimiter, Iterable) .

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

Evidemment pas beaucoup d’utilisation en dehors d’Android, mais je pensais que je l’appendais à ce sujet …

Télécharger le Jakarta Commons Lang et utiliser la méthode

  SsortingngUtils.join(list) 

Bien sûr, vous pouvez l’implémenter vous-même, mais leur code est entièrement testé et constitue 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.

C’est une question assez ancienne, mais je pense que je pourrais tout aussi bien append une réponse plus moderne – utilisez la classe Joiner de Guava :

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

Changer la liste en une chaîne lisible et significative est vraiment une question commune à chacun.

Cas 1 . Si vous avez des SsortingngUtils d’Apache dans votre chemin de classe (comme rogerdpack et Ravi Wallau):

 import org.apache.commons.lang3.SsortingngUtils; Ssortingng str = SsortingngUtils.join(myList); 

Cas 2 . Si vous voulez seulement utiliser les moyens de JDK (7):

 import java.util.Arrays; Ssortingng str = Arrays.toSsortingng(myList.toArray()); 

Ne construisez jamais de roues par vous-même, n’utilisez pas de boucle pour cette tâche sur une ligne.

Si vous cherchiez un traceur rapide à partir de Java 5, vous pouvez le faire:

 myList.toSsortingng().replaceAll("\\[|\\]", "").replaceAll(", ","\t") 

De plus, si votre but est simplement d’imprimer le contenu et que vous êtes moins préoccupé par le “\ t”, vous pouvez simplement faire ceci:

 myList.toSsortingng() 

qui retourne une chaîne comme

[str1, str2, str3]

Si vous avez un tableau (pas ArrayList), vous pouvez accomplir la même chose comme ceci:

  Arrays.toSsortingng(myList).replaceAll("\\[|\\]", "").replaceAll(", ","\t") 

Faites une boucle à travers et appelez à Chaîne. Il n’y a pas de moyen magique, et s’il y en avait, que pensez-vous que cela ferait sous les couvertures, sauf en les parcourant? À propos de la seule micro-optimisation, utilisez SsortingngBuilder au lieu de Ssortingng, et même ce n’est pas un gain énorme – la concaténation des chaînes devient SsortingngBuilder sous les couvertures, mais au moins si vous écrivez de cette manière, vous pourrez voir ce qui se passe.

 SsortingngBuilder out = new SsortingngBuilder(); for (Object o : list) { out.append(o.toSsortingng()); out.append("\t"); } return out.toSsortingng(); 

La plupart des projets Java ont souvent des langages apache-commons disponibles. Les méthodes SsortingngUtils.join () sont très intéressantes et ont plusieurs saveurs pour répondre à presque tous les besoins.

 public static java.lang.Ssortingng join(java.util.Collection collection, char separator) public static Ssortingng join(Iterator iterator, Ssortingng separator) { // handle null, zero and one elements before building a buffer Object first = iterator.next(); if (!iterator.hasNext()) { return ObjectUtils.toSsortingng(first); } // two or more elements SsortingngBuffer buf = new SsortingngBuffer(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.toSsortingng(); } 

Paramètres:

collection – La collection de valeurs à réunir peut être nulle

séparateur – le caractère séparateur à utiliser

Retourne : la chaîne jointe, null si entrée d’iterator null

Depuis: 2.3

Android a une classe TextUtil que vous pouvez utiliser http://developer.android.com/reference/android/text/TextUtils.html

 Ssortingng implode = TextUtils.join("\t", list); 

Une manière élégante de traiter les caractères de séparation de fin est d’utiliser le séparateur de classes

 SsortingngBuilder buf = new SsortingngBuilder(); Separator sep = new Separator("\t"); for (Ssortingng each: list) buf.append(sep).append(each); Ssortingng s = buf.toSsortingng(); 

La méthode toSsortingng de Class Separator renvoie le séparateur, à l’ exception du premier appel. Ainsi, nous imprimons la liste sans traçage (ou dans ce cas) des séparateurs principaux.

C’est un algorithme O(n) toute façon (sauf si vous avez fait une solution multithread où vous avez divisé la liste en plusieurs sous-listes, mais je ne pense pas que ce soit ce que vous demandez).

Utilisez simplement un SsortingngBuilder comme ci-dessous:

 SsortingngBuilder sb = new SsortingngBuilder(); for (Object obj : list) { sb.append(obj.toSsortingng()); sb.append("\t"); } Ssortingng finalSsortingng = sb.toSsortingng(); 

SsortingngBuilder sera beaucoup plus rapide que la concaténation de chaînes car vous ne ré-instanciez pas un object Ssortingng à chaque concaténation.

ArrayList classe ArrayList ( Java Docs ) étend la classe AbstractList , qui étend la classe AbstractCollection qui contient une toSsortingng() ( Java Docs ). Donc, vous écrivez simplement

 listName.toSsortingng(); 

Les développeurs Java ont déjà trouvé le moyen le plus efficace et vous en ont donné une méthode bien organisée et documentée. Appelez simplement cette méthode.

Pour ce cas d’utilisation simple, vous pouvez simplement joindre les chaînes avec une virgule. Si vous utilisez Java 8:

 Ssortingng csv = Ssortingng.join("\t", yourArray); 

sinon commons-lang a une méthode join ():

 Ssortingng csv = org.apache.commons.lang3.SsortingngUtils.join(yourArray, "\t"); 

Dans le cas où vous êtes sur Android et que vous n’utilisez pas encore Jack (par exemple parce qu’il manque encore de support pour Instant Run), et si vous souhaitez davantage de contrôle sur le formatage de la chaîne résultante (par exemple, le diviseur d’éléments), et si vous utilisez / souhaitez utiliser la bibliothèque StreamSupport (pour utiliser des stream sur Java 7 ou des versions antérieures du compilateur), vous pouvez utiliser quelque chose comme ça (je mets cette méthode dans ma classe ListUtils):

 public static  Ssortingng asSsortingng(List list) { return StreamSupport.stream(list) .map(Object::toSsortingng) .collect(Collectors.joining("\n")); } 

Et bien sûr, assurez-vous d’implémenter toSsortingng () sur la classe de vos objects de liste.

Peut-être pas la meilleure façon, mais élégante.

Arrays.deepToSsortingng (Arrays.asList (“Test”, “Test2”)

 import java.util.Arrays; public class Test { public static void main(Ssortingng[] args) { System.out.println(Arrays.deepToSsortingng(Arrays.asList("Test", "Test2").toArray())); } } 

Sortie

[Test, Test2]

Si vous utilisez des collections Eclipse , vous pouvez utiliser la méthode makeSsortingng() .

 ArrayList list = new ArrayList(); list.add("one"); list.add("two"); list.add("three"); Assert.assertEquals( "one\ttwo\tthree", ArrayListAdapter.adapt(list).makeSsortingng("\t")); 

Si vous pouvez convertir votre ArrayList en FastList , vous pouvez vous en débarrasser.

 Assert.assertEquals( "one\ttwo\tthree", FastList.newListWith("one", "two", "three").makeSsortingng("\t")); 

Note: Je suis un committer pour les collections Eclipse.

 List ssortingngList = getMyListOfSsortingngs(); SsortingngJoiner sj = new SsortingngJoiner(" "); ssortingngList.stream().forEach(e -> sj.add(e)); Ssortingng spaceSeparated = sj.toSsortingng() 

Vous transmettez au new SsortingngJoiner la séquence de caractères que vous voulez utiliser comme séparateur. Si vous voulez faire un CSV: new SsortingngJoiner(", ");

Le code ci-dessous peut vous aider,

 List list = new ArrayList(); list.add("1"); list.add("2"); list.add("3"); Ssortingng str = list.toSsortingng(); System.out.println("Step-1 : " + str); str = str.replaceAll("[\\[\\]]", ""); System.out.println("Step-2 : " + str); 

Sortie:

 Step-1 : [1, 2, 3] Step-2 : 1, 2, 3 

En Java 8, c’est simple. Voir exemple de liste d’entiers:

 Ssortingng result = Arrays.asList(1,2,3).stream().map(Object::toSsortingng).reduce((t, u) -> t + "\t" + u).orElse(""); 

Ou version multiligne (plus simple à lire):

 Ssortingng result = Arrays.asList(1,2,3).stream() .map(Object::toSsortingng) .reduce((t, u) -> t + "\t" + u) .orElse(""); 

Serait-ce une bonne chose:

 List streamValues = new ArrayList<>(); Arrays.deepToString(streamValues.toArray())); 

Si vous ne voulez pas le dernier \ t après le dernier élément, vous devez utiliser l’index pour vérifier, mais rappelez-vous que cela ne “fonctionne” (c.-à-d. O (n)) lorsque la liste implémente RandomAccess.

 List list = new ArrayList(); list.add("one"); list.add("two"); list.add("three"); SsortingngBuilder sb = new SsortingngBuilder(list.size() * apprAvg); // every apprAvg > 1 is better than none for (int i = 0; i < list.size(); i++) { sb.append(list.get(i)); if (i < list.size() - 1) { sb.append("\t"); } } System.out.println(sb.toString()); 

Pour séparer en utilisant des tabs au lieu d’utiliser println, vous pouvez utiliser l’ impression

  ArrayList mylist = new ArrayList(); mylist.add("C Programming"); mylist.add("Java"); mylist.add("C++"); mylist.add("Perl"); mylist.add("Python"); for (Ssortingng each : mylist) { System.out.print(each); System.out.print("\t"); } 

Je vois pas mal d’exemples qui dépendent de ressources supplémentaires, mais il semble que ce serait la solution la plus simple: (ce que j’ai utilisé dans mon propre projet) qui consiste simplement à convertir une ArrayList en Array puis en List. .

  List accounts = new ArrayList<>(); public String accountList() { Account[] listingArray = accounts.toArray(new Account[accounts.size()]); String listingString = Arrays.toString(listingArray); return listingString; } 

C’est une conversation assez ancienne à l’heure actuelle et apache commons utilise désormais un SsortingngBuilder en interne: http://commons.apache.org/lang/api/src-html/org/apache/commons/lang/SsortingngUtils.html#line. 3045

Nous soaps que cela améliorera les performances, mais si la performance est critique, la méthode utilisée pourrait être quelque peu inefficace. Alors que l’interface est flexible et permet un comportement cohérent entre différents types de collections, elle est quelque peu inefficace pour les listes, qui est le type de collection dans la question originale.

Je me base sur le fait que nous subissons des frais généraux que nous éviterions en parcourant simplement les éléments d’une boucle for traditionnelle. Au lieu de cela, il y a des choses supplémentaires qui se passent en arrière pour vérifier les modifications simultanées, les appels de méthode, etc. La boucle améliorée entraînera par contre la même surcharge puisque l’iterator est utilisé sur l’object Iterable (la liste).

Vous pouvez utiliser une expression régulière pour cela. C’est aussi concis que ça devient

 System.out.println(yourArrayList.toSsortingng().replaceAll("\\[|\\]|[,][ ]","\t")); 

Que diriez-vous de cette fonction:

 public static Ssortingng toSsortingng(final Collection collection) { final SsortingngBuilder sb = new SsortingngBuilder("{"); boolean isFirst = true; for (final Object object : collection) { if (!isFirst) sb.append(','); else isFirst = false; sb.append(object); } sb.append('}'); return sb.toSsortingng(); } 

ça marche pour tout type de collection …

En une ligne: De [12,0,1,78,12] à 12 0 1 78 12

 Ssortingng srt= list.toSsortingng().replaceAll("\\[|\\]|,","");