简体   繁体   English

如何在Java中打印出List的所有元素?

[英]How to print out all the elements of a List in Java?

I am trying to print out all the elements of a List , however it is printing the pointer of the Object rather than the value.我试图打印出List所有元素,但是它打印的是Object的指针而不是值。

This is my printing code...这是我的打印代码...

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

Could anyone please help me why it isn't printing the value of the elements.任何人都可以帮助我为什么它不打印元素的值。

The following is compact and avoids the loop in your example code (and gives you nice commas):以下内容很紧凑,避免了示例代码中的循环(并为您提供了漂亮的逗号):

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

However, as others have pointed out, if you don't have sensible toString() methods implemented for the objects inside the list, you will get the object pointers (hash codes, in fact) you're observing.但是,正如其他人指出的那样,如果您没有为列表中的对象实现合理的 toString() 方法,您将获得您正在观察的对象指针(实际上是哈希码)。 This is true whether they're in a list or not.无论它们是否在列表中,都是如此。

Here is some example about getting print out the list component:下面是一些关于打印列表组件的示例:

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

从 Java 8 开始,List 继承了默认的“forEach”方法,您可以将其与方法引用“System.out::println”结合,如下所示:

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

toString() of AbstractCollection will be clean and easy enough to do that . AbstractCollection toString()将很干净而且很容易做到这一点 AbstractList is a subclass of AbstractCollection , so no need to for loop and no toArray() needed. AbstractList是子类AbstractCollection因此无需对循环且无需指定者()。

Returns a string representation of this collection.返回此集合的字符串表示形式。 The string representation consists of a list of the collection's elements in the order they are returned by its iterator, enclosed in square brackets ("[]").字符串表示由集合元素的列表组成,按其迭代器返回的顺序排列,括在方括号(“[]”)中。 Adjacent elements are separated by the characters ", " (comma and space).相邻元素由字符“,”(逗号和空格)分隔。 Elements are converted to strings as by String.valueOf(Object).元素通过 String.valueOf(Object) 转换为字符串。

If you are using any custom object in your list, say Student , you need to override its toString() method(it is always good to override this method) to have a meaningful output如果您在列表中使用任何自定义对象,例如 Student ,您需要覆盖其toString()方法(覆盖此方法总是好的)以获得有意义的输出

See the below example:请参阅以下示例:

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

output:输出:

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

使用String.join()例如:

System.out.print(String.join("\n", list));

Java 8 Streams 方法...

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

The objects in the list must have toString implemented for them to print something meaningful to screen.列表中的对象必须为它们实现toString以向屏幕打印有意义的内容。

Here's a quick test to see the differences:这是一个快速测试以查看差异:

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

And when this executes, the results printed to screen are:当它执行时,打印到屏幕的结果是:

t1 = Test$T1@19821f
t2 = 5

Since T1 does not override the toString method, its instance t1 prints out as something that isn't very useful.由于 T1 没有覆盖 toString 方法,它的实例 t1 打印出来的东西不是很有用。 On the other hand, T2 overrides toString, so we control what it prints when it is used in I/O, and we see something a little better on screen.另一方面,T2 覆盖了 toString,因此我们可以控制它在 I/O 中使用时打印的内容,并且我们在屏幕上看到了一些更好的东西。

Or you could simply use the Apache Commons utilities:或者您可以简单地使用 Apache Commons 实用程序:

https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ArrayUtils.html#toString-java.lang.Object- https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ArrayUtils.html#toString-java.lang.Object-

List<MyObject> myObjects = ...
System.out.println(ArrayUtils.toString(myObjects));

Consider a List<String> stringList which can be printed in many ways using Java 8 constructs:考虑一个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)

How are these approaches different from each other?这些方法有何不同?

First Approach ( Iterable.forEach )- The iterator of the collection is generally used and that is designed to be fail-fast which means it will throw ConcurrentModificationException if the underlying collection is structurally modified during the iteration.第一种方法( Iterable.forEach )-通常使用集合的迭代器,它被设计为快速失败,这意味着如果在迭代过程中对底层集合进行了结构修改,它将抛出ConcurrentModificationException As mentioned in the doc for ArrayList :ArrayList 文档中所述:

A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array;结构修改是添加或删除一个或多个元素或显式调整后备数组大小的任何操作; merely setting the value of an element is not a structural modification.仅仅设置元素的值不是结构修改。

So it means for ArrayList.forEach setting the value is allowed without any issue.所以这意味着对于ArrayList.forEach设置该值是允许的,没有任何问题。 And in case of concurrent collection eg ConcurrentLinkedQueue the iterator would be weakly-consistent which means the actions passed in forEach are allowed to make even structural changes without ConcurrentModificationException exception being thrown.并且在并发收集的情况下,例如ConcurrentLinkedQueue ,迭代器将是弱一致的,这意味着允许在forEach中传递的操作进行结构更改,而不会引发ConcurrentModificationException异常。 But here the modifications might or might not be visible in that iteration.但在这里,修改可能会或可能不会在该迭代中可见。

Second Approach ( Stream.forEach )- The order is undefined.第二种方法 ( Stream.forEach )-顺序未定义。 Though it may not occur for sequential streams but the specification does not guarantee it.虽然它可能不会发生在顺序流中,但规范并不能保证它。 Also the action is required to be non-interfering in nature.还要求该动作本质上是非干扰性的。 As mentioned in doc :文档中所述

The behavior of this operation is explicitly nondeterministic.此操作的行为明显是不确定的。 For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism.对于并行流管道,此操作不保证遵守流的遇到顺序,因为这样做会牺牲并行性的好处。

Third Approach ( Stream.forEachOrdered )- The action would be performed in the encounter order of the stream.第三种方法( Stream.forEachOrdered )-操作将按照流的遇到顺序执行。 So whenever order matters use forEachOrdered without a second thought.因此,每当订单很重要时,请forEachOrdered使用forEachOrdered As mentioned in the doc :文档中所述:

Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order.如果流具有定义的遇到顺序,则按流的遇到顺序对此流的每个元素执行操作。

While iterating over a synchronized collection the first approach would take the collection's lock once and would hold it across all the calls to action method, but in case of streams they use collection's spliterator, which does not lock and relies on the already established rules of non-interference.在迭代同步集合时第一种方法将获取集合的锁一次,并在所有对 action 方法的调用中保持它,但在流的情况下,它们使用集合的拆分器,它不锁定并依赖于已经建立的非规则-干涉。 In case collection backing the stream is modified during iteration a ConcurrentModificationException would be thrown or inconsistent result may occur.如果在迭代期间修改了支持流的集合,则会抛出ConcurrentModificationException或可能出现不一致的结果。

Fourth Approach (Parallel Stream.forEach )- As already mentioned no guarantee to respect the encounter order as expected in case of parallel streams.第四种方法(Parallel Stream.forEach )-正如已经提到的,在并行流的情况下,不能保证按照预期的方式尊重遭遇顺序。 It is possible that action is performed in different thread for different elements which can never be the case with forEachOrdered .对于不同的元素,可能在不同的线程中执行操作,而forEachOrdered永远不会出现这种情况。

Fifth Approach (Parallel Stream.forEachOrdered )- The forEachOrdered will process the elements in the order specified by the source irrespective of the fact whether stream is sequential or parallel.第五种方法(Parallel Stream.forEachOrdered )- forEachOrdered将按照源指定的顺序处理元素,而不管流是顺序还是并行。 So it makes no sense to use this with parallel streams.因此,将其与并行流一起使用是没有意义的。

I have faced similar problems.我也遇到过类似的问题。 My code:我的代码:

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

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

Way 1: printing a list in a for loop方式1:在for循环中打印列表

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

Way 2: printing the list in a forEach, for loop方式 2:在 forEach、for 循环中打印列表

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

Way 3: printing the list in java 8方式3:在java 8中打印列表

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

By using java 8 features. 通过使用Java 8功能。

import java.util.Arrays;
import java.util.List;

/**
 * @author AJMAL SHA
 *
 */
public class ForEach {

    public static void main(String[] args) {

        List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
        (features).forEach(System.out::println);

    }

}
  1. You haven't specified what kind of elements the list contains, if it is a primitive data type then you can print out the elements.您还没有指定列表包含什么类型的元素,如果它是原始数据类型,那么您可以打印出这些元素。
  2. But if the elements are objects then as Kshitij Mehta mentioned you need to implement (override) the method "toString" within that object - if it is not already implemented - and let it return something meaning full from within the object, example:但是,如果元素是对象,那么正如 Kshitij Mehta 提到的,您需要在该对象中实现(覆盖)方法“toString” - 如果它尚未实现 - 并让它从对象内部返回一些含义完整的东西,例如:

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

对于字符串数组的列表

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

For loop to print the content of a list : For 循环打印列表的内容:

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

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

Result :结果 :

Element : AA
Element : BB

If you want to print in a single line (just for information) :如果您想在一行中打印(仅供参考):

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

Result :结果 :

Elements : AA, BB

System.out.println(list); works for me.为我工作。

Here is a full example:这是一个完整的例子:

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

It will print [Hello, World] .它将打印[Hello, World]

I wrote a dump function, which basicly prints out the public members of an object if it has not overriden toString().我写了一个转储函数,它基本上打印出一个对象的公共成员,如果它没有覆盖 toString()。 One could easily expand it to call getters.人们可以轻松地将其扩展为调用 getter。 Javadoc: Javadoc:

Dumps an given Object to System.out, using the following rules:使用以下规则将给定对象转储到 System.out:

  • If the Object is Iterable, all of its components are dumped.如果 Object 是 Iterable,则转储其所有组件。
  • If the Object or one of its superclasses overrides toString(), the "toString" is dumped如果对象或其超类之一覆盖 toString(),则转储“toString”
  • Else the method is called recursively for all public members of the Object否则,该方法会为对象的所有公共成员递归调用

/**
 * 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();
}
    list.stream().map(x -> x.getName()).forEach(System.out::println);

It depends on what type of objects stored in the List , and whether it has implementation for toString() method.这取决于存储在List的对象类型,以及它是否具有toString()方法的实现。 System.out.println(list) should print all the standard java object types ( String , Long , Integer etc). System.out.println(list)应该打印所有标准的 java 对象类型( StringLongInteger等)。 In case, if we are using custom object types, then we need to override toString() method of our custom object.如果我们使用自定义对象类型,那么我们需要override自定义对象的toString()方法。

Example:例子:

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

I happen to be working on this now...我碰巧现在正在做这个......

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

try to override toString() method as you want that the element will be printend.尝试覆盖 toString() 方法,因为您希望元素将被打印结束。 so the method to print can be this:所以打印的方法可以是这样的:

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

Solusion of your problem for java 11 is:您对 java 11 的问题的解决方案是:

String separator = ", ";
String toPrint = list.stream().map(o -> String.valueOf(o)).collect(Collectors.joining(separator));

System.out.println(toPrint);
   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;
     }
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM