Come stampare tutti gli elementi di un elenco in Java?


236

Sto cercando di stampare tutti gli elementi di a List, tuttavia sta stampando il puntatore del Objectanziché il valore.

Questo è il mio codice di stampa ...

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

Qualcuno potrebbe aiutarmi perché non stampa il valore degli elementi.


3
Che tipo hai dichiarato Listdi essere? Mostraci come l'hai dichiarato e istanziato.
Makoto,

devi chiamare toString e otterrai una spiegazione della classe o sovrascrivere il metodo toString per il tipo che contiene l'elenco
L7ColWinters

Questo è ciò che stai dicendo di stampare: hai bisogno di una stringa diversa o altra stringa leggibile.
Dave Newton,

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

4
Si noti che c'è una sintassi più compatta è possibile utilizzare per ottenere la stessa cosa: for (Object obj : list) {System.out.println(obj);}.
aroth

Risposte:


114

Ecco alcuni esempi su come stampare il componente elenco:

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
In che modo l'introduzione della Modelclasse è collegata alla domanda?
Karl Richter,

4
È solo un presupposto, dal momento che non so che tipo di oggetto all'interno dell'elenco.
Crazenezz,

477

Quanto segue è compatto ed evita il ciclo nel tuo codice di esempio (e ti dà delle belle virgole):

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

Tuttavia, come altri hanno sottolineato, se non hai metodi toString () sensibili implementati per gli oggetti all'interno dell'elenco, otterrai i puntatori agli oggetti (codici hash, in effetti) che stai osservando. Questo è vero se sono in un elenco o no.


18
Che dire solo list.toString().
Jaskey,

22
L'uso di 'list.toString ()' non stampa i singoli elementi, a meno che non sia un'implementazione personalizzata dell'interfaccia Elenco che sovrascrive il comportamento normale (per stampare il nome della classe e un codice hash, più o meno).
Holly Cummins,

1
Se usano la classe personalizzata e non sovrascrivono toString, la soluzione stampa anche il nome della sua classe e il codice hash.
Jaskey,

Stampa come [valore1, valore2, valore3]. Possiamo stampare come senza []?
deadend

In realtà, @Jaskey ha ragione: la loro risposta è migliore. Il Arraysmetodo è utile per gli array, ma ora non è necessario per le sottoclassi di AbstractCollection.
Holly Cummins,

100

Da Java 8, List eredita un metodo "forEach" predefinito che puoi combinare con il riferimento al metodo "System.out :: println" in questo modo:

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

2
@ Katja Hahn, è possibile aggiungere o anteporre una stringa printlnall'output?
Gumkins,

2
@gumkins, SÌ, puoi. Esempio: Arrays.stream (nuova stringa [] {"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()di AbstractCollection sarà pulito e abbastanza facile da farlo . AbstractListè una sottoclasse di AbstractCollection, quindi non è necessario per loop e non è necessario toArray ().

Restituisce una rappresentazione in formato stringa di questa raccolta. La rappresentazione in formato stringa consiste in un elenco degli elementi della raccolta nell'ordine in cui sono restituiti dal relativo iteratore, racchiuso tra parentesi quadre ("[]"). Gli elementi adiacenti sono separati dai caratteri "," (virgola e spazio). Gli elementi vengono convertiti in stringhe come da String.valueOf (Object).

Se stai usando un oggetto personalizzato nel tuo elenco, ad esempio Studente, devi sovrascrivere il suo toString()metodo (è sempre utile sovrascrivere questo metodo) per avere un risultato significativo

Vedi l'esempio seguente:

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;
    }
}

produzione:

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

Perché questa risposta non è del tutto corretta. Sta usando il polimorfismo senza accorgersene. Ecco la gerarchia di ereditarietà effettiva per list: List -> Collection -> Iterable -> Object. La classe che eredita effettivamente da AbstractCollection è ArrayList. Quindi in questo esempio quando toString()viene chiamato trova l' ArrayListimplementazione che è definita in AbstractCollection. Nota la gerarchia ereditaria per ArrayList:ArrayList -> AbstractList -> AbstractCollection -> Collection -> Iterable -> Object
anon58192932

20

L'approccio Java 8 Streams ...

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

stessa risposta di Katja Hahn
Karl Richter,

No non lo è. Il mio sfrutta stream ().
Bradley D,

@BradleyD quali vantaggi si ottengono aggiungendo un altro livello di chiamate di metodo lì?
Leon,

15

Gli oggetti nell'elenco devono essere toStringimplementati per poter stampare qualcosa di significativo sullo schermo.

Ecco un breve test per vedere le differenze:

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

E quando questo viene eseguito, i risultati stampati sullo schermo sono:

t1 = Test$T1@19821f
t2 = 5

Poiché T1 non sovrascrive il metodo toString, la sua istanza t1 viene stampata come qualcosa che non è molto utile. D'altra parte, T2 sovrascrive a String, quindi controlliamo ciò che stampa quando viene utilizzato in I / O e vediamo qualcosa di un po 'meglio sullo schermo.


11

Considera un List<String> stringListche può essere stampato in molti modi usando costrutti 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)

In che modo questi approcci sono diversi l'uno dall'altro?

Primo approccio ( Iterable.forEach) - L'iteratore della raccolta viene generalmente utilizzato e progettato per essere fail-fast, il che significa che verrà lanciato ConcurrentModificationExceptionse la raccolta sottostante viene modificata strutturalmente durante l'iterazione. Come menzionato nel documento per ArrayList:

Una modifica strutturale è qualsiasi operazione che aggiunge o elimina uno o più elementi o ridimensiona esplicitamente l'array di supporto; la semplice impostazione del valore di un elemento non è una modifica strutturale.

Quindi significa ArrayList.forEachche l'impostazione del valore è consentita senza alcun problema. E in caso di raccolta simultanea, ad es. ConcurrentLinkedQueueL'iteratore sarebbe debolmente coerente, il che significa che alle azioni passate forEachè consentito apportare anche cambiamenti strutturali senza ConcurrentModificationExceptioneccezioni. Ma qui le modifiche potrebbero o meno essere visibili in quella iterazione.

Secondo approccio ( Stream.forEach): l'ordine non è definito. Anche se potrebbe non verificarsi per flussi sequenziali, ma le specifiche non lo garantiscono. Inoltre, l'azione deve essere di natura non interferente. Come menzionato nel documento :

Il comportamento di questa operazione è esplicitamente non deterministico. Per le condotte di flusso parallelo, questa operazione non garantisce il rispetto dell'ordine di incontro del flusso, poiché ciò sacrificherebbe il vantaggio del parallelismo.

Terzo Approccio (Stream.forEachOrdered ): l'azione verrà eseguita nell'ordine di incontro del flusso. Quindi, ogni volta che l'ordine conta, usa forEachOrderedsenza pensarci due volte. Come menzionato nel documento :

Esegue un'azione per ciascun elemento di questo flusso, nell'ordine di incontro del flusso se il flusso ha un ordine di incontro definito.

Durante l'iterazione su a raccolta sincronizzata, il primo approccio prenderebbe una volta il blocco della raccolta e lo terrà su tutti i metodi di invito all'azione, ma in caso di flussi usano lo splitterator della raccolta, che non si blocca e si basa sulle regole già stabilite di non -interference. Nel caso in cui il backup della raccolta venga modificato durante lo iterazione, lo stream ConcurrentModificationExceptionverrebbe generato o potrebbe verificarsi un risultato incoerente.

Quarto approccio (parallelo Stream.forEach ) - Come già accennato, nessuna garanzia di rispettare l'ordine dell'incontro come previsto in caso di flussi paralleli. È possibile che l'azione venga eseguita in thread diversi per elementi diversi, cosa che non è mai possibile forEachOrdered.

Quinto Approach (parallelo Stream.forEachOrdered) - La forEachOrderedelaborerà gli elementi nell'ordine specificato dalla sorgente indipendentemente dal fatto se stream è sequenziale o parallelo. Quindi non ha senso usarlo con flussi paralleli.




7

Ho affrontato problemi simili. Il mio codice:

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

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

Modo 1: stampare un elenco in un ciclo for

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

Modo 2: stampare l'elenco in forEach, per loop

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

Modo 3: stampare l'elenco in java 8

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

5
  1. Non hai specificato quale tipo di elementi contiene l'elenco, se si tratta di un tipo di dati primitivo, puoi stampare gli elementi.
  2. Ma se gli elementi sono oggetti, come ha detto Kshitij Mehta, è necessario implementare (sovrascrivere) il metodo "toString" all'interno di quell'oggetto - se non è già implementato - e lasciarlo restituire qualcosa che significhi pieno dall'interno dell'oggetto, esempio:

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

3

System.out.println(list); per me va bene.

Ecco un esempio completo:

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

Stamperà [Hello, World].


Non diverso dalle altre precedenti risposte
Karl Richter,

Ho fornito un esempio completo con importazioni, classe e metodo principale che è possibile copiare e incollare e mostrato il risultato. Pertanto, nessun motivo per votare a mio avviso
jfmg

3

Per un elenco di array di stringhe

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

2

Ho scritto una funzione di dump, che in sostanza stampa i membri pubblici di un oggetto se non ha sostituito aString (). Si potrebbe facilmente espanderlo per chiamare getter. javadoc:

Esegue il dump di un determinato oggetto su System.out, utilizzando le seguenti regole:

  • Se l'oggetto è Iterable, tutti i suoi componenti vengono scaricati.
  • Se l'oggetto o una delle sue superclassi sostituisce toString (), viene eseguito il dump di "toString"
  • Altrimenti il ​​metodo viene chiamato in modo ricorsivo per tutti i membri pubblici dell'Oggetto

/**
 * 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

Per loop per stampare il contenuto di un elenco:

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

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

Risultato:

Element : AA
Element : BB

Se si desidera stampare su una sola riga (solo per informazione):

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

Risultato:

Elements : AA, BB

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

Che tipo ha xe in che modo è collegato alla domanda del PO?
Karl Richter,

1

Mi capita di lavorare su questo ora ...

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

Dipende dal tipo di oggetti archiviati nel Liste se ha un'implementazione per il toString()metodo. System.out.println(list)dovrebbe stampare tutti i tipi di oggetti Java Standard ( String, Long, Integerecc). Nel caso, se stiamo usando tipi di oggetti personalizzati, allora abbiamo bisogno del override toString()metodo del nostro oggetto personalizzato.

Esempio:

class Employee {
 private String name;
 private long id;

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

Test:

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

prova a sovrascrivere il metodo toString () come desideri che l'elemento sia printend. quindi il metodo per stampare può essere questo:

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

Questo è ciò che fa il codice OP. La chiamata a toStringè implicita.
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;
     }
   }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.