Jak wydrukować wszystkie elementy Listy w Javie?

236

Próbuję wydrukować wszystkie elementy a List, ale wypisuje wskaźnik Objectraczej niż wartość.

To jest mój kod do drukowania ...

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

Czy ktoś mógłby mi pomóc, dlaczego nie drukuje wartości elementów.

użytkownik1335361
źródło
3
Jakiego rodzaju zadeklarowałeś List? Pokaż, jak to zadeklarowałeś i utworzyłeś instancję.
Makoto
musisz wywołać toString, a otrzymasz wyjaśnienie klasy lub zastąpić metodę toString dla typu, który zawiera lista
L7ColWinters
Właśnie to każe ci wydrukować - potrzebujesz innego toString lub innego czytelnego ciągu.
Dave Newton
ArrayList <class> list = new ArrayList <class> ();
user1335361
4
Zauważ, że nie ma bardziej zwartą składni można użyć, aby osiągnąć to samo: for (Object obj : list) {System.out.println(obj);}.
aroth

Odpowiedzi:

114

Oto kilka przykładów wypisywania składnika listy:

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;
    }
}
Crazenezz
źródło
1
W jaki sposób wprowadzenie Modelklasy jest powiązane z pytaniem?
Karl Richter
4
To tylko założenie, ponieważ nie wiem, jaki obiekt znajduje się na liście.
Crazenezz
477

Poniższy kod jest zwarty i pozwala uniknąć pętli w przykładowym kodzie (i daje ładne przecinki):

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

Jednak, jak zauważyli inni, jeśli nie masz zaimplementowanych sensownych metod toString () dla obiektów na liście, dostaniesz obserwowane wskaźniki obiektów (kody skrótu). Dzieje się tak niezależnie od tego, czy są na liście, czy nie.

Holly Cummins
źródło
18
A co tylko z tym list.toString().
Jaskey
22
Samo użycie „list.toString ()” nie spowoduje wydrukowania poszczególnych elementów, chyba że jest to niestandardowa implementacja interfejsu List, która zastępuje normalne zachowanie (aby wydrukować nazwę klasy i kod skrótu, mniej więcej).
Holly Cummins,
1
Jeśli używają niestandardowej klasy i nie zastępują toString, rozwiązanie wydrukuje również nazwę swojej klasy i kod skrótu.
Jaskey
Drukuje się jako [wartość1, wartość2, wartość3]. Czy możemy drukować bez []?
deadend
W rzeczywistości @Jaskey ma rację - ich odpowiedź jest lepsza. Ta Arraysmetoda jest pomocna w przypadku tablic, ale nie jest teraz potrzebna w przypadku podklas AbstractCollection.
Holly Cummins,
100

Od wersji Java 8 List dziedziczy domyślną metodę „forEach”, którą można połączyć z referencją do metody „System.out :: println” w następujący sposób:

list.forEach(System.out::println);
Karsten Hahn
źródło
2
@Katja Hahn, czy można dołączyć lub przygotować ciąg znaków do printlnwyjścia?
gumkins
2
@umumkins, TAK, możesz. Przykład: 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()o AbstractCollection będzie czyste i dość łatwe do zrobienia, że . AbstractListjest podklasą AbstractCollection, więc nie ma potrzeby używania pętli ani funkcji toArray ().

Zwraca ciąg reprezentujący tę kolekcję. Reprezentacja ciągu składa się z listy elementów kolekcji w kolejności, w jakiej są zwracane przez iterator, ujętej w nawiasy kwadratowe („[]”). Sąsiadujące elementy są oddzielone znakami „,” (przecinek i spacja). Elementy są konwertowane na ciągi znaków przez String.valueOf (Object).

Jeśli używasz dowolnego niestandardowego obiektu na liście, powiedzmy Student, musisz przesłonić jego toString()metodę (zawsze warto przesłonić tę metodę), aby uzyskać znaczący wynik

Zobacz poniższy przykład:

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

wynik:

[string1, string2]
[student Tom age:15, student Kate age:16]
Jaskey
źródło
Ponieważ ta odpowiedź nie jest do końca poprawna. Wykorzystuje polimorfizm, nie zdając sobie z tego sprawy. Oto rzeczywista hierarchia dziedziczenia dla list: List -> Collection -> Iterable -> Object. Jest to klasa, która faktycznie dziedziczy po AbstractCollection ArrayList. Tak więc w tym przykładzie po toString()wywołaniu znajduje ArrayListimplementację zdefiniowaną w AbstractCollection. Zwróć uwagę na hierarchię dziedziczenia dla ArrayList:ArrayList -> AbstractList -> AbstractCollection -> Collection -> Iterable -> Object
anon58192932
20

Podejście do strumieni Java 8 ...

list.stream().forEach(System.out::println);
Bradley D.
źródło
taka sama odpowiedź jak Katja Hahn
Karl Richter
Nie, nie jest. Mine wykorzystuje stream ().
Bradley D,
@BradleyD jakie zyski są osiągane przez dodanie tam kolejnej warstwy wywołań metod?
Leon,
15

Obiekty na liście muszą mieć toStringzaimplementowane, aby mogły wydrukować coś ważnego do zeskanowania.

Oto szybki test, aby zobaczyć różnice:

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

Po uruchomieniu wyniki wydrukowane na ekranie są następujące:

t1 = Test$T1@19821f
t2 = 5

Ponieważ T1 nie zastępuje metody toString, jego instancja t1 jest drukowana jako coś, co nie jest bardzo przydatne. Z drugiej strony, T2 przesłania toString, więc kontrolujemy, co drukuje, gdy jest używane we / wy, i widzimy coś nieco lepszego na ekranie.

K Mehta
źródło
11

Zastanów się, List<String> stringListktóre można wydrukować na wiele sposobów za pomocą konstrukcji 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)

Czym różnią się od siebie te podejścia?

Pierwsze podejście ( Iterable.forEach) - zazwyczaj używany jest iterator kolekcji, który jest zaprojektowany tak, aby działał szybko, co oznacza, że ​​zostanie rzucony, ConcurrentModificationExceptionjeśli podstawowa kolekcja zostanie zmodyfikowana strukturalnie podczas iteracji. Jak wspomniano w dokumencie dla ArrayList:

Modyfikacja strukturalna to dowolna operacja, która dodaje lub usuwa jeden lub więcej elementów lub wyraźnie zmienia rozmiar tablicy pomocniczej; samo ustawienie wartości elementu nie jest modyfikacją strukturalną.

Oznacza to, że ArrayList.forEachustawienie wartości jest dozwolone bez żadnych problemów. A w przypadku równoczesnego gromadzenia, np ConcurrentLinkedQueue. Iterator byłby słabo spójny, co oznacza, że ​​przekazane działania forEachmogą dokonywać nawet zmian strukturalnych bez ConcurrentModificationExceptionwyjątku. Ale tutaj modyfikacje mogą, ale nie muszą być widoczne w tej iteracji.

Drugie podejście ( Stream.forEach) - Kolejność jest niezdefiniowana. Chociaż może nie wystąpić w przypadku strumieni sekwencyjnych, ale specyfikacja tego nie gwarantuje. Konieczne jest również, aby działanie nie miało charakteru zakłócającego. Jak wspomniano w dokumencie :

Zachowanie tej operacji jest wyraźnie niedeterministyczne. W przypadku potoków strumienia równoległego ta operacja nie gwarantuje przestrzegania kolejności spotkania strumienia, ponieważ spowodowałoby to poświęcenie korzyści z równoległości.

Trzecie podejście ( Stream.forEachOrdered) - Akcja zostanie wykonana w kolejności spotkania strumienia. Tak więc zawsze, gdy liczy się kolejność, korzystaj forEachOrderedbez zastanowienia. Jak wspomniano w dokumencie :

Wykonuje akcję dla każdego elementu tego strumienia, w kolejności spotkania strumienia, jeśli strumień ma zdefiniowaną kolejność spotkań.

Podczas iteracji nad zsynchronizowanym kolekcji na pierwsze podejście byłoby wziąć blokadę kolekcji na raz i będzie trzymać go we wszystkich wywołań metody działania, ale w przypadku strumieni używają spliterator kolekcji, która nie blokuje i opiera się na już ustalonych zasad niedziałania -ingerencja. W przypadku zmodyfikowania kopii zapasowej strumienia podczas iteracji ConcurrentModificationExceptionzostanie wyrzucony lub może wystąpić niespójny wynik.

Czwarte podejście (równoległe Stream.forEach) - jak już wspomniano, nie ma gwarancji przestrzegania kolejności spotkań zgodnie z oczekiwaniami w przypadku strumieni równoległych. Możliwe jest, że akcja jest wykonywana w innym wątku dla różnych elementów, co nigdy nie jest możliwe forEachOrdered.

Piąty Approach (równolegle Stream.forEachOrdered) -forEachOrdered przetwarza elementy w kolejności określonej przez źródła, niezależnie od tego, czy strumień jest kolejno lub równolegle. Dlatego nie ma sensu używać tego z równoległymi strumieniami.

akhil_mittal
źródło
9

Użyj String.join() na przykład:

System.out.print(String.join("\n", list)));
Łukasz Ochmański
źródło
7

Miałem podobne problemy. Mój kod:

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

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

Sposób 1: wydrukowanie listy w pętli for

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

Sposób 2: wydrukowanie listy w pętli forEach, for

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

Sposób 3: Wydrukuj listę w Javie 8

leaveDatesList.forEach(System.out::println);
Atequer Rahman
źródło
5
  1. Nie określiłeś, jakie elementy zawiera lista, jeśli jest to prymitywny typ danych , możesz wydrukować elementy.
  2. Ale jeśli elementy są obiektami, to jak wspomniał Kshitij Mehta, musisz zaimplementować (przesłonić) metodę „toString” w tym obiekcie - jeśli jeszcze nie został zaimplementowany - i pozwolić mu zwrócić coś znaczącego z wnętrza obiektu, przykład:

    class Person {
        private String firstName;
        private String lastName;
    
        @Override
        public String toString() {
            return this.firstName + " " + this.lastName;
        }
    }
Sam
źródło
3

System.out.println(list); pracuje dla mnie.

Oto pełny przykład:

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

Wydrukuje się [Hello, World].

jfmg
źródło
Nie różni się od innych wcześniejszych odpowiedzi
Karl Richter
Podałem pełny przykład z importem, klasą i główną metodą, którą można skopiować i wkleić, i pokazałem wynik. Dlatego moim zdaniem nie ma powodu, aby głosować w dół
jfmg
3

Aby uzyskać listę tablic String

list.forEach(s -> System.out.println(Arrays.toString((String[]) s )));
Belchior Palma
źródło
2

Napisałem funkcję zrzutu, która zasadniczo drukuje publiczne elementy obiektu, jeśli nie zastąpiło toString (). Można go łatwo rozwinąć, aby wywoływać osoby pobierające. Javadoc:

Zrzuca dany obiekt do System.out, stosując następujące reguły:

  • Jeśli Obiekt jest Iterowalny, wszystkie jego komponenty są zrzucane.
  • Jeśli obiekt lub jedna z jego nadklas zastępuje metodę toString (), „toString” jest zrzucany
  • W przeciwnym razie metoda jest wywoływana rekurencyjnie dla wszystkich publicznych członków obiektu

/**
 * 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();
}
Michael A. Schaffrath
źródło
2

Aby pętla wypisała zawartość listy:

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

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

Wynik:

Element : AA
Element : BB

Jeśli chcesz drukować w jednym wierszu (tylko dla informacji):

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

Wynik:

Elements : AA, BB
Théo Moulia
źródło
1
    list.stream().map(x -> x.getName()).forEach(System.out::println);
Ella
źródło
Jaki typ ma xi jak ma się to do pytania PO?
Karl Richter
1

Tak się składa, że ​​pracuję teraz nad tym ...

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);
wayneseymour
źródło
1

Zależy to od rodzaju obiektów przechowywanych w Listi od tego, czy ma implementację dla toString()metody. System.out.println(list)Należy wydrukować wszystkie standardowe typy obiektów Java ( String, Long, Integeretc). W przypadku, gdy używamy niestandardowych typów obiektów, musimy override toString()zastosować metodę naszego niestandardowego obiektu.

Przykład:

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);
   }
}
Shravan Ramamurthy
źródło
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()));
    }
Alexander Mladzhov
źródło
0

spróbuj przesłonić metodę toString (), jeśli chcesz, aby element był drukowany. więc metoda drukowania może być następująca:

for(int i=0;i<list.size();i++){
    System.out.println(list.get(i).toString());
} 
riccardo_castellano
źródło
Tak właśnie działa kod PO. Wezwanie do toStringjest niejawne.
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;
     }
   }
sharath
źródło