Як роздрукувати всі елементи списку на Java?


236

Я намагаюся роздрукувати всі елементи а List, проте це друк покажчика, Objectа не значення.

Це мій код друку ...

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

Чи може хтось допомогти мені, чому він не друкує значення елементів.


3
Якого типу ти оголосив List? Покажіть нам, як ви це заявили та підтвердили.
Макото

вам потрібно зателефонувати до toString, і ви отримаєте пояснення щодо класу або замініть метод toString для типу, який міститься у списку
L7ColWinters

Це те, що ви говорите йому для друку - вам потрібна інша тота String або інший читабельний рядок.
Дейв Ньютон

ArrayList <class> list = новий ArrayList <class> ();
користувач1335361

4
Зверніть увагу , що є більш компактний синтаксис можна використовувати для виконання тих же речей: for (Object obj : list) {System.out.println(obj);}.
aroth

Відповіді:


114

Ось приклад отримання роздруківки компонента списку:

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
Як вступ до Modelкласу пов'язаний із питанням?
Карл Ріхтер

4
Це лише припущення, оскільки я не знаю, що таке об’єкт у списку.
Crazenezz

477

Далі є компактним і дозволяє уникнути циклу у вашому прикладі коду (і дає приємні коми):

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

Однак, як зазначали інші, якщо у вас немає розумних методів toString (), реалізованих для об'єктів всередині списку, ви отримаєте об'єктні покажчики (насправді хеш-коди), які ви спостерігаєте. Це вірно, чи є вони у списку чи ні.


18
А що тільки list.toString().
Жаскі

22
Просто використання "list.toString ()" не буде друкувати окремі елементи, якщо тільки це не власна реалізація інтерфейсу "Список", що переосмислює нормальну поведінку (для друку назви класу та хеш-коду, більш-менш).
Холлі Каммінз

1
Якщо вони використовують користувальницький клас і не переосмислюють toString, ваше рішення також надрукує його ім'я класу та хеш-код.
Jaskey

Він друкується як [value1, value2, value3]. Чи можемо ми друкувати як без []?
декад

Насправді @Jaskey має рацію - їх відповідь краща. ArraysМетод корисний для масивів, але тепер не потрібно для підкласів AbstractCollection.
Холлі Каммінс

100

Оскільки Java 8, List успадковує за замовчуванням метод "forEach", який ви можете комбінувати з посиланням на метод "System.out :: println", як це:

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

2
@Katja Hahn, чи можна додати чи додати якийсь рядок до printlnвиводу?
gumkins

2
@gumkins, ТАК, ти можеш. Приклад: Arrays.stream (новий String [] {"John", "Sansa", "Cersei"}). Map (s -> "Привіт" + s + "!"). ForEach (System.out :: println) ;
Тіаго Мусі

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

toString()з AbstractCollection буде чистою і досить легко , щоб зробити це . AbstractListє підкласом AbstractCollection, тому немає необхідності в циклі і не потрібен toArray ().

Повертає рядкове подання цієї колекції. Представлення рядків складається із списку елементів колекції у порядку їх повернення ітератором, укладеним у квадратні дужки ("[]"). Суміжні елементи розділені символами "," (кома та пробіл). Елементи перетворюються на рядки, як String.valueOf (Object).

Якщо ви використовуєте будь-який нестандартний об'єкт у своєму списку, скажімо, Student, вам потрібно переосмислити його toString()метод (завжди добре замінити цей метод), щоб мати значущий результат

Дивіться приклад нижче:

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

вихід:

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

Тому що ця відповідь не зовсім правильна. Це використання поліморфізму, не усвідомлюючи цього. Ось фактична ієрархія наслідування list: List -> Collection -> Iterable -> Object. Клас, який насправді успадковує від AbstractCollection ArrayList. Отже, у цьому прикладі, коли toString()він називається, він знаходить ArrayListреалізацію, яка визначена в AbstractCollection. Зверніть увагу на ієрархію спадкування для ArrayList:ArrayList -> AbstractList -> AbstractCollection -> Collection -> Iterable -> Object
anon58192932

20

Підхід потоків Java 8 ...

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

така ж відповідь, як у Каті Хан
Карл Ріхтер

Ні, це не так. Потік шахтного плеча ().
Бредлі D

@BradleyD які надбавки реалізуються додавши туди ще один шар викликів методу?
Леон

15

Об'єкти зі списку повинні бути toStringреалізовані для того, щоб надрукувати на екрані щось значиме.

Ось короткий тест, щоб побачити відмінності:

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

І коли це виконується, результати, що друкуються на екрані:

t1 = Test$T1@19821f
t2 = 5

Оскільки T1 не замінює метод toString, його екземпляр t1 друкується як щось, що не дуже корисно. З іншого боку, T2 перекриває ToString, тому ми контролюємо, що він друкує, коли він використовується у вході / виводі, і ми бачимо щось трохи краще на екрані.


11

Розглянемо, List<String> stringListяку можна надрукувати багатьма способами за допомогою конструкцій 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)

Чим ці підходи відрізняються один від одного?

Перший підхід ( Iterable.forEach) - Ітератор колекції, як правило, використовується, і він розроблений таким чином, що не виходить з ладу, а це означає, що він викине, ConcurrentModificationExceptionякщо базова колекція буде структурно модифікована під час ітерації. Як зазначено в документі для ArrayList:

Структурна модифікація - це будь-яка операція, яка додає або видаляє один або кілька елементів або явно змінює розмір резервного масиву; просто встановлення значення елемента не є структурною модифікацією.

Таким чином, це означає, що ArrayList.forEachвстановлення значення дозволено без жодних питань. А у випадку одночасного збору, наприклад, ConcurrentLinkedQueueітератор буде слабко узгодженим, що означає дії, що передаютьсяforEach виконані дії дозволяють вносити навіть структурні зміни без ConcurrentModificationExceptionвинятку. Але тут модифікації можуть бути або не помітні в цій ітерації.

Другий підхід ( Stream.forEach) - Порядок не визначений. Хоча це може не траплятися для послідовних потоків, але специфікація цього не гарантує. Також дії повинні мати не заважаючий характер. Як згадується в документі :

Поведінка цієї операції явно недетерміновано. Для паралельних потокових трубопроводів ця операція не гарантує дотримання порядку зустрічі потоку, оскільки це може принести шкоду паралелізму.

Третій підхід ( Stream.forEachOrdered) - Дія буде виконуватися в порядку зустрічі потоку. Тож, коли питання про замовлення використовуйте, forEachOrderedне замислюючись. Як зазначено в документі :

Виконує дію для кожного елемента цього потоку в порядку зустрічі потоку, якщо потік має визначений порядок зустрічі.

У той час як ітерація по синхронному колекції з першим підходом б заблокувати колекцію раз і проведуть його через всі виклики до методу дії, але в разі потоків , які вони використовують spliterator колекції, яка не блокує і спирається на вже встановлені правила неурядового -втручання. У випадку, якщо резервна копія потоку колекції буде змінена під час ітерації, це ConcurrentModificationExceptionможе бути кинуто або може виникнути непослідовий результат.

Четвертий підхід (паралельний Stream.forEach) - Як вже було сказано, жодна гарантія дотримання порядку зустрічей, як очікувалося, у разі паралельних потоків. Можливо, що дії виконуються в різних нитках для різних елементів, що ніколи не може бути з цим forEachOrdered.

П'ятий підхід (паралельний Stream.forEachOrdered) -forEachOrdered буде обробляти елементи в порядку , зазначеному джерелі , незалежно від того , чи є послідовний або паралельний потік. Тому немає сенсу використовувати це при паралельних потоках.




7

Я зіткнувся з подібними проблемами. Мій код:

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

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

Спосіб 1: друк списку в циклі for

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

Спосіб 2: друк списку в forEach, для циклу

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

Спосіб 3: друк списку в java 8

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

5
  1. Ви не вказали, які елементи містить список, якщо це примітивний тип даних то ви можете роздрукувати елементи.
  2. Але якщо елементи є об'єктами, тоді, як згадував Кшитій Мехта, вам потрібно реалізувати (замінити) метод "toString" всередині цього об'єкта - якщо він ще не реалізований - і нехай він поверне щось об'єктне значення зсередини об'єкта, наприклад:

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

3

System.out.println(list); працює для мене.

Ось повний приклад:

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

Він надрукує [Hello, World].


Не відрізняється від інших, більш ранніх відповідей
Карл Ріхтер

Я наводив повний приклад з імпортом, класом та основним методом, який ви можете скопіювати та вставити, і показав результат. Тому, на мою думку, немає підстав проголосувати це
jfmg


2

Я написав дамп-функцію, яка в основному виводить публічні члени об'єкта, якщо він не перекрив toString (). Можна було легко розширити його на дзвінки. Javadoc:

Скидає заданий об’єкт на System.out, використовуючи такі правила:

  • Якщо Об'єкт є Ітерабельним, всі його компоненти скидаються.
  • Якщо Об'єкт або один із його суперклассів перекриває ToString (), "toString" скидається
  • В іншому випадку метод називається рекурсивно для всіх громадських членів Об'єкта

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

Для циклу друку вмісту списку:

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

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

Результат:

Element : AA
Element : BB

Якщо ви хочете надрукувати в один рядок (лише для інформації):

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

Результат:

Elements : AA, BB


1

Я, мабуть, працюю над цим зараз ...

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

Це залежить від того, який тип об'єктів зберігається в Listі чи є у нього реалізація для toString()методу. System.out.println(list)повинен друкувати всі стандартні типи об'єктів Java ( String, Long, і Integerт.д.). У випадку, якщо ми використовуємо власні типи об’єктів, то нам це потрібноoverride toString() метод нашого власного об'єкта.

Приклад:

class Employee {
 private String name;
 private long id;

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

Тест:

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

спробуйте замінити метод toString () так, як ви хочете, щоб елемент був принтеном. тож спосіб друку може бути таким:

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

Ось що робить код ОП. Заклик до toString- неявний.
Карл Ріхтер

-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;
     }
   }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.