Comment imprimer tous les éléments d'une liste en Java?


236

J'essaie d'imprimer tous les éléments d'un List, mais il imprime le pointeur du Objectplutôt que la valeur.

Ceci est mon code d'impression ...

for(int i=0;i<list.size();i++){
    System.out.println(list.get(i));
} 

Quelqu'un pourrait-il m'aider à comprendre pourquoi il n'imprime pas la valeur des éléments.


3
Quel type avez-vous déclaré Listêtre? Montrez-nous comment vous l'avez déclaré et instancié.
Makoto

vous devez appeler toString et vous obtiendrez une explication de la classe ou substituerez la méthode toString pour le type que la liste contient
L7ColWinters

C'est ce que vous lui dites d'imprimer - vous avez besoin d'une autre chaîne toString ou d'une autre chaîne lisible.
Dave Newton

ArrayList <class> list = new ArrayList <class> ();
user1335361

4
Notez qu'il ya une syntaxe plus compacte que vous pouvez utiliser pour accomplir la même chose: for (Object obj : list) {System.out.println(obj);}.
2012

Réponses:


114

Voici quelques exemples pour imprimer le composant liste:

public class ListExample {

    public static void main(String[] args) {
        List<Model> models = new ArrayList<>();

        // TODO: First create your model and add to models ArrayList, to prevent NullPointerException for trying this example

        // Print the name from the list....
        for(Model model : models) {
            System.out.println(model.getName());
        }

        // Or like this...
        for(int i = 0; i < models.size(); i++) {
            System.out.println(models.get(i).getName());
        }
    }
}

class Model {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

1
Quel est le Modellien entre l'introduction de la classe et la question?
Karl Richter

4
C'est juste une hypothèse, car je ne sais pas quel type d'objet à l'intérieur de la liste.
Crazenezz

477

Ce qui suit est compact et évite la boucle dans votre exemple de code (et vous donne de belles virgules):

System.out.println(Arrays.toString(list.toArray()));

Cependant, comme d'autres l'ont souligné, si vous n'avez pas de méthodes toString () implémentées pour les objets de la liste, vous obtiendrez les pointeurs d'objet (codes de hachage, en fait) que vous observez. Cela est vrai, qu'ils soient dans une liste ou non.


18
Et seulement list.toString().
Jaskey

22
L'utilisation de 'list.toString ()' n'imprimera pas les éléments individuels, sauf s'il s'agit d'une implémentation personnalisée de l'interface List qui remplace le comportement normal (pour imprimer le nom de la classe et un code de hachage, plus ou moins).
Holly Cummins

1
S'ils utilisent une classe personnalisée et ne remplacent pas toString, votre solution imprime également son nom de classe et son code de hachage.
Jaskey

Il s'imprime comme [valeur1, valeur2, valeur3]. Peut-on imprimer comme sans []?
deadend

En fait, @Jaskey a raison - leur réponse est meilleure. La Arraysméthode est utile pour les tableaux, mais n'est plus nécessaire pour les sous-classes de AbstractCollection.
Holly Cummins

100

Depuis Java 8, List hérite d'une méthode "forEach" par défaut que vous pouvez combiner avec la référence de méthode "System.out :: println" comme ceci:

list.forEach(System.out::println);

2
@ Katja Hahn, est-il possible d'ajouter ou de pré-ajouter une chaîne à la printlnsortie?
gumkins

2
@gumkins, OUI, vous le pouvez. Exemple: Arrays.stream (new String [] {"John", "Sansa", "Cersei"}). Map (s -> "Hi" + s + "!"). ForEach (System.out :: println) ;
Tiago Mussi

40
System.out.println(list);//toString() is easy and good enough for debugging.

toString()de AbstractCollection sera propre et assez facile à faire . AbstractListest une sous-classe de AbstractCollection, donc pas besoin de boucle et aucun toArray () n'est nécessaire.

Renvoie une représentation sous forme de chaîne de cette collection. La représentation sous forme de chaîne consiste en une liste des éléments de la collection dans l'ordre dans lequel ils sont renvoyés par son itérateur, entre crochets ("[]"). Les éléments adjacents sont séparés par les caractères "," (virgule et espace). Les éléments sont convertis en chaînes comme par String.valueOf (Object).

Si vous utilisez un objet personnalisé dans votre liste, par exemple Student, vous devez remplacer sa toString()méthode (il est toujours bon de remplacer cette méthode) pour avoir une sortie significative

Voir l'exemple ci-dessous:

public class TestPrintElements {

    public static void main(String[] args) {

        //Element is String, Integer,or other primitive type
        List<String> sList = new ArrayList<String>();
        sList.add("string1");
        sList.add("string2");
        System.out.println(sList);

        //Element is custom type
        Student st1=new Student(15,"Tom");
        Student st2=new Student(16,"Kate");
        List<Student> stList=new ArrayList<Student>();
        stList.add(st1);
        stList.add(st2);
        System.out.println(stList);
   }
}


public  class Student{
    private int age;
    private String name;

    public Student(int age, String name){
        this.age=age;
        this.name=name;
    }

    @Override
    public String toString(){
        return "student "+name+", age:" +age;
    }
}

production:

[string1, string2]
[student Tom age:15, student Kate age:16]

Parce que cette réponse n'est pas entièrement correcte. Il utilise le polymorphisme sans s'en rendre compte. Voici la hiérarchie d'héritage réel pour list: List -> Collection -> Iterable -> Object. La classe qui hérite réellement de AbstractCollection est ArrayList. Ainsi, dans cet exemple, lorsque toString()est appelé, il trouve l' ArrayListimplémentation définie dans AbstractCollection. Notez la hiérarchie d'héritage pour ArrayList:ArrayList -> AbstractList -> AbstractCollection -> Collection -> Iterable -> Object
anon58192932

20

L'approche Java 8 Streams ...

list.stream().forEach(System.out::println);

même réponse que celle de Katja Hahn
Karl Richter

Non ça ne l'est pas. La mine exploite le flux ().
Bradley D

@BradleyD quels gains sont réalisés en y ajoutant une autre couche d'appels de méthode?
Leon

15

Les objets de la liste doivent avoir toStringimplémenté pour qu'ils puissent imprimer quelque chose de significatif à l'écran.

Voici un test rapide pour voir les différences:

public class Test {

    public class T1 {
        public Integer x;
    }

    public class T2 {
        public Integer x;

        @Override
        public String toString() {
            return x.toString();
        }
    }

    public void run() {
        T1 t1 = new T1();
        t1.x = 5;
        System.out.println(t1);

        T2 t2 = new T2();
        t2.x = 5;
        System.out.println(t2);

    }

    public static void main(String[] args) {        
        new Test().run();
    }
}

Et lorsque cela s'exécute, les résultats imprimés à l'écran sont:

t1 = Test$T1@19821f
t2 = 5

Puisque T1 ne remplace pas la méthode toString, son instance t1 s'affiche comme quelque chose qui n'est pas très utile. D'un autre côté, T2 remplace toString, nous contrôlons donc ce qu'il imprime lorsqu'il est utilisé dans les E / S, et nous voyons quelque chose d'un peu mieux à l'écran.


11

Considérez un List<String> stringListqui peut être imprimé de plusieurs façons en utilisant des constructions Java 8 :

stringList.forEach(System.out::println);                            // 1) Iterable.forEach
stringList.stream().forEach(System.out::println);                   // 2) Stream.forEach (order maintained generally but doc does not guarantee)
stringList.stream().forEachOrdered(System.out::println);            // 3) Stream.forEachOrdered (order maintained always)
stringList.parallelStream().forEach(System.out::println);           // 4) Parallel version of Stream.forEach (order not maintained)
stringList.parallelStream().forEachOrdered(System.out::println);    // 5) Parallel version ofStream.forEachOrdered (order maintained always)

En quoi ces approches sont-elles différentes les unes des autres?

Première approche ( Iterable.forEach) - L'itérateur de la collection est généralement utilisé et il est conçu pour être infaillible, ce qui signifie qu'il sera lancé ConcurrentModificationExceptionsi la collection sous-jacente est structurellement modifiée pendant l'itération. Comme mentionné dans le doc pour ArrayList:

Une modification structurelle est toute opération qui ajoute ou supprime un ou plusieurs éléments, ou redimensionne explicitement le tableau de support; la simple définition de la valeur d'un élément n'est pas une modification structurelle.

Cela signifie donc que la ArrayList.forEachdéfinition de la valeur est autorisée sans aucun problème. Et en cas de collecte simultanée, par exemple, ConcurrentLinkedQueuel'itérateur serait faiblement cohérent, ce qui signifie que les actions transmises forEachsont autorisées à effectuer des changements structurels réguliers sans ConcurrentModificationExceptionexception. Mais ici, les modifications peuvent être visibles ou non dans cette itération.

Deuxième approche ( Stream.forEach) - L'ordre n'est pas défini. Bien que cela ne puisse pas se produire pour les flux séquentiels, la spécification ne le garantit pas. L'action doit également être de nature non interférente. Comme mentionné dans le doc :

Le comportement de cette opération est explicitement non déterministe. Pour les pipelines de flux parallèles, cette opération ne garantit pas de respecter l'ordre de rencontre du flux, car cela sacrifierait l'avantage du parallélisme.

Troisième approche ( Stream.forEachOrdered) - L'action serait exécutée dans l'ordre de rencontre du flux. Donc, chaque fois que l'ordre compte, utilisez forEachOrderedsans arrière-pensée. Comme mentionné dans le doc :

Effectue une action pour chaque élément de ce flux, dans l' ordre de rencontre du flux si le flux a un ordre de rencontre défini.

Lors de l'itération sur une collection synchronisée, la première approche prendrait le verrou de la collection une fois et le maintiendrait sur tous les appels à la méthode d'action, mais dans le cas des flux, ils utilisent le séparateur de la collection, qui ne se verrouille pas et s'appuie sur les règles de non -ingérence. Dans le cas où la collection sauvegardant le flux est modifiée pendant l'itération, un résultat ConcurrentModificationExceptionserait levé ou un résultat incohérent pourrait se produire.

Quatrième approche (parallèle Stream.forEach) - Comme déjà mentionné, aucune garantie de respecter l'ordre de rencontre comme prévu en cas de flux parallèles. Il est possible que l'action soit effectuée dans différents threads pour différents éléments, ce qui ne peut jamais être le cas forEachOrdered.

Cinquième approche (parallèle Stream.forEachOrdered) - Le forEachOrderedtraitera les éléments dans l'ordre spécifié par la source, que le flux soit séquentiel ou parallèle. Cela n'a donc aucun sens de l'utiliser avec des flux parallèles.




7

J'ai rencontré des problèmes similaires. Mon code:

List<Integer> leaveDatesList = new ArrayList<>();

.....inserted value in list.......

Méthode 1: impression d'une liste dans une boucle for

for(int i=0;i<leaveDatesList.size();i++){
    System.out.println(leaveDatesList.get(i));
}

Méthode 2: impression de la liste dans une boucle forEach, for

for(Integer leave : leaveDatesList){
    System.out.println(leave);
}

Méthode 3: impression de la liste en Java 8

leaveDatesList.forEach(System.out::println);

5
  1. Vous n'avez pas spécifié quel type d'éléments la liste contient, s'il s'agit d'un type de données primitif, vous pouvez imprimer les éléments.
  2. Mais si les éléments sont des objets, comme Kshitij Mehta l'a mentionné, vous devez implémenter (remplacer) la méthode "toString" au sein de cet objet - s'il n'est pas déjà implémenté - et le laisser renvoyer quelque chose de plein à l'intérieur de l'objet, exemple:

    class Person {
        private String firstName;
        private String lastName;
    
        @Override
        public String toString() {
            return this.firstName + " " + this.lastName;
        }
    }

3

System.out.println(list); travaille pour moi.

Voici un exemple complet:

import java.util.List;    
import java.util.ArrayList;

public class HelloWorld {
     public static void main(String[] args) {
        final List<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("World");
        System.out.println(list);
     }
}

Il s'imprimera [Hello, World].


Pas différent des autres réponses précédentes
Karl Richter

J'ai donné un exemple complet avec les importations, la classe et la méthode principale que vous pouvez copier et coller et j'ai montré le résultat. Par conséquent, aucune raison de voter contre à mon avis
jfmg

3

Pour une liste de tableau de String

list.forEach(s -> System.out.println(Arrays.toString((String[]) s )));

2

J'ai écrit une fonction de vidage, qui affiche simplement les membres publics d'un objet s'il n'a pas remplacé toString (). On pourrait facilement l'étendre pour appeler des getters. Javadoc:

Vide un objet donné dans System.out, en utilisant les règles suivantes:

  • Si l'objet est itérable, tous ses composants sont vidés.
  • Si l'objet ou l'une de ses superclasses remplace toString (), le "toString" est vidé
  • Sinon, la méthode est appelée récursivement pour tous les membres publics de l'objet

/**
 * Dumps an given Object to System.out, using the following rules:<br>
 * <ul>
 * <li> If the Object is {@link Iterable}, all of its components are dumped.</li>
 * <li> If the Object or one of its superclasses overrides {@link #toString()}, the "toString" is dumped</li>
 * <li> Else the method is called recursively for all public members of the Object </li>
 * </ul>
 * @param input
 * @throws Exception
 */
public static void dump(Object input) throws Exception{
    dump(input, 0);
}

private static void dump(Object input, int depth) throws Exception{
    if(input==null){
        System.out.print("null\n"+indent(depth));
        return;
    }

    Class<? extends Object> clazz = input.getClass();
    System.out.print(clazz.getSimpleName()+" ");
    if(input instanceof Iterable<?>){
        for(Object o: ((Iterable<?>)input)){
            System.out.print("\n"+indent(depth+1));
            dump(o, depth+1);
        }
    }else if(clazz.getMethod("toString").getDeclaringClass().equals(Object.class)){
        Field[] fields = clazz.getFields();
        if(fields.length == 0){
            System.out.print(input+"\n"+indent(depth));
        }
        System.out.print("\n"+indent(depth+1));
        for(Field field: fields){
            Object o = field.get(input);
            String s = "|- "+field.getName()+": ";
            System.out.print(s);
            dump(o, depth+1);
        }
    }else{

        System.out.print(input+"\n"+indent(depth));
    }
}

private static String indent(int depth) {
    StringBuilder sb = new StringBuilder();
    for(int i=0; i<depth; i++)
        sb.append("  ");
    return sb.toString();
}

2

For loop pour imprimer le contenu d'une liste:

List<String> myList = new ArrayList<String>();
myList.add("AA");
myList.add("BB");

for ( String elem : myList ) {
  System.out.println("Element : "+elem);
}

Résultat :

Element : AA
Element : BB

Si vous souhaitez imprimer sur une seule ligne (juste pour information):

String strList = String.join(", ", myList);
System.out.println("Elements : "+strList);

Résultat :

Elements : AA, BB

1
    list.stream().map(x -> x.getName()).forEach(System.out::println);

Quel type a xet comment est-il lié à la question du PO?
Karl Richter

1

Il se trouve que je travaille là-dessus maintenant ...

List<Integer> a = Arrays.asList(1, 2, 3);
List<Integer> b = Arrays.asList(3, 4);
List<int[]> pairs = a.stream()
  .flatMap(x -> b.stream().map(y -> new int[]{x, y}))
  .collect(Collectors.toList());

Consumer<int[]> pretty = xs -> System.out.printf("\n(%d,%d)", xs[0], xs[1]);
pairs.forEach(pretty);

1

Cela dépend du type d'objets stockés dans le List, et s'il a une implémentation pour la toString()méthode. System.out.println(list)devrait imprimer tous les types standard de l' objet java ( String, Long, Integeretc.). Dans le cas, si nous utilisons des types d'objets personnalisés, nous devons alors utiliser la override toString()méthode de notre objet personnalisé.

Exemple:

class Employee {
 private String name;
 private long id;

 @Override
 public String toString() {
   return "name: " + this.name() + 
           ", id: " + this.id();
 }  
}

Tester:

class TestPrintList {
   public static void main(String[] args) {
     Employee employee1 =new Employee("test1", 123);
     Employee employee2 =new Employee("test2", 453);
     List<Employee> employees = new ArrayList(2);
     employee.add(employee1);
     employee.add(employee2);
     System.out.println(employees);
   }
}

0
public static void main(String[] args) {
        answer(10,60);

    }
    public static void answer(int m,int k){
        AtomicInteger n = new AtomicInteger(m);
        Stream<Integer> stream = Stream.generate(() -> n.incrementAndGet()).limit(k);
        System.out.println(Arrays.toString(stream.toArray()));
    }

0

essayez de remplacer la méthode toString () comme vous voulez que l'élément soit printend. donc la méthode pour imprimer peut être la suivante:

for(int i=0;i<list.size();i++){
    System.out.println(list.get(i).toString());
} 

C'est ce que fait le code OP. L'appel à toStringest implicite.
Karl Richter

-2
   List<String> textList=  messageList.stream()
                            .map(Message::getText)
                            .collect(Collectors.toList());

        textList.stream().forEach(System.out::println);
        public class Message  {

        String name;
        String text;

        public Message(String name, String text) {
            this.name = name;
            this.text = text;
        }

        public String getName() {
            return name;
        }

      public String getText() {
        return text;
     }
   }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.