java arraylist<> - Meilleure façon de convertir une ArrayList en chaîne




14 Answers

Fondamentalement, l'utilisation d'une boucle pour itérer sur ArrayList est la seule option:

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

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 va être très bien, car le compilateur javac optimisera la concaténation de chaînes comme une série d'opérations d' append sur un StringBuilder toute façon. Voici une partie du désassemblage du bytecode de la boucle for 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 cette boucle en utilisant un StringBuilder , donc la performance ne devrait pas être un gros problème.

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

En fait, je pense que tout type de sortie (que ce soit sur le disque ou sur l'écran) aura au moins un ordre de grandeur plus lent que de devoir s'inquiéter 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 StringBuilder à 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 instancie un seul objet StringBuilder dehors de la boucle for .

Réécrire le code ci-dessus pour:

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());

Instanciera seulement le StringBuilder une fois en dehors de la boucle, et fera seulement les deux appels à la méthode append à l'intérieur de la boucle, comme en témoigne ce bytecode (qui montre l'instanciation de 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, 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 StringBuilder à chaque itération.

example syntax

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 le parcourir (ou supprimer chaque élément) et le concaténer à une chaîne mais je pense que cela sera très lent.




Si vous faites cela sur Android, il y a un bon utilitaire pour ce qu'on appelle TextUtils qui a une .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 ...




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

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



Si vous recherchez un one-liner rapide, à partir de Java 5, vous pouvez faire ceci:

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

De plus, si votre but est simplement d'imprimer le contenu et que vous vous souciez moins du "\ t", vous pouvez simplement faire ceci:

myList.toString()

qui renvoie une chaîne comme

[str1, str2, str3]

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

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



La plupart des projets Java ont souvent des langages apache-commons disponibles. StringUtils.join () méthodes est très agréable et a plusieurs saveurs pour répondre à presque tous les besoins.

public static java.lang.String join(java.util.Collection collection,
                                    char separator)


public static String join(Iterator iterator, String separator) {
    // handle null, zero and one elements before building a buffer 
    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();
}

Paramètres:

collection - la collection de valeurs à joindre, peut être nulle

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

Retourne : l'entrée String, null si null itérateur

Depuis: 2.3




Une façon élégante de gérer les caractères de séparation à la fin est d'utiliser le séparateur de classes

StringBuilder buf = new StringBuilder();
Separator sep = new Separator("\t");
for (String each: list) buf.append(sep).append(each);
String s = buf.toString();

La méthode toString de Class Separator renvoie le séparateur, sauf pour le premier appel. Ainsi nous imprimons la liste sans trailing (ou dans ce cas) des séparateurs principaux.




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

listName.toString();

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




Peut ne pas être le meilleur moyen, mais de manière élégante.

Arrays.deepToString (Arrays.asList ("Test", "Test2")

import java.util.Arrays;

    public class Test {
        public static void main(String[] args) {
            System.out.println(Arrays.deepToString(Arrays.asList("Test", "Test2").toArray()));
        }
    }

Sortie

[Test, Test2]




Le code ci-dessous peut vous aider,

List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
String str = list.toString();
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



Est-ce que ce qui suit serait bon?

List<String> 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 que (c'est-à-dire O (n)) quand les listes implémentent le RandomAccess.

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

StringBuilder sb = new StringBuilder(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());



Vous pouvez utiliser un Regex pour cela. C'est aussi concis que possible

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



C'est une conversation plutôt ancienne et les communs apache utilisent maintenant un StringBuilder en interne: http://commons.apache.org/lang/api/src-html/org/apache/commons/lang/StringUtils.html#line.3045

Ce sera comme nous savons améliorer la performance, mais si la performance est critique, la méthode utilisée peut être quelque peu inefficace. Alors que l'interface est flexible et permet un comportement cohérent entre différents types de collection, elle est quelque peu inefficace pour les listes, qui est le type de collection dans la question d'origine.

Je base cela en ce que nous encourons des frais généraux que nous éviterions en itérant simplement à travers les éléments dans une boucle for traditionnelle. Au lieu de cela, il se passe des choses supplémentaires en arrière-scène pour vérifier les modifications simultanées, les appels de méthode, etc. La boucle for enhanced entraîne le même surcoût puisque l'itérateur est utilisé sur l'objet Iterable (la liste).




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

String srt= list.toString().replaceAll("\\[|\\]|,","");



Related

java string arraylist