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

我试图打印出List的所有元素,但是它打印的是Object的指针而不是值。

这是我的打印代码…

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

有人能告诉我为什么它不打印元素的值吗?

1269977 次浏览

列表中的对象必须实现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,所以我们控制了它在I/O中使用时打印的内容,我们在屏幕上看到了一些更好的东西。

  1. 你还没有指定列表包含什么类型的元素,如果它是基元数据类型,那么你可以打印出元素。
  2. 但是如果元素是对象,那么就像Kshitij Mehta提到的,你需要在该对象中实现(覆盖)方法"toString" -如果它还没有实现-并让它从对象中返回一些有意义的东西,例如:

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

下面是一些关于打印list组件的例子:

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

下面的代码很紧凑,避免了示例代码中的循环(并提供了漂亮的逗号):

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

然而,正如其他人指出的那样,如果您没有为列表中的对象实现合理的toString()方法,您将得到您所观察到的对象指针(实际上是哈希码)。无论它们是否在列表中,都是如此。

从Java 8开始,List继承了一个默认的“forEach”方法,你可以将它与方法引用“System”结合起来使用。输出::println”像这样:

list.forEach(System.out::println);
我写了一个转储函数,它基本上打印出一个对象的公共成员,如果它没有覆盖toString()。可以很容易地将其扩展为调用getter。 Javadoc: < / p >

将给定对象转储到系统。输出,使用以下规则:

  • 如果对象是Iterable,则它的所有组件都将被转储。
  • 如果Object或它的一个超类覆盖了toString(),则“toString”将被转储
  • 否则,该方法将为对象的所有公共成员递归调用
  • < / ul > < / p >
/**
* 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();
}
System.out.println(list);//toString() is easy and good enough for debugging.

__ABC0AbstractCollection将是干净和容易做到这一点AbstractListAbstractCollection因此不需要for循环和toArray()。的子类

返回该集合的字符串表示形式。字符串表示形式由集合元素的列表组成 它们由迭代器返回的顺序,用方括号括起来 (“[]”)。相邻元素用字符“,”(逗号)分隔 和空间)。通过将元素转换为字符串 String.valueOf(对象). < / p >

如果你正在使用列表中的任何自定义对象,比如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]

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]

Java 8 Streams方法…

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

用于String数组的列表

list.forEach(s -> System.out.println(Arrays.toString((String[]) s )));
   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;
}
}
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()));
}

尝试重写toString()方法,因为您希望元素将被打印。 打印的方法可以是:

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

考虑一个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,迭代器将是weakly-consistent,这意味着在forEach中传递的操作甚至可以在不抛出ConcurrentModificationExceptionexception的情况下进行结构更改。但是这里的修改可能在迭代中可见,也可能不可见。

第二方法(Stream.forEach)- 顺序没有定义。虽然它可能不会出现在连续流中,但规范并不能保证它。此外,该行为还必须是不干涉性质的。正如医生中提到的:

此操作的行为是显式的不确定的。为 平行流管道,此操作不保证 尊重溪流的遭遇顺序,因为这样做会牺牲 并行的好处。

第三种方法(Stream.forEachOrdered)- 该操作将按照流的遇到顺序执行。因此,只要顺序有问题,就可以毫不犹豫地使用forEachOrdered。正如在医生中提到的:

.

相遇中为该流的每个元素执行一个操作 如果流有定义的遇到顺序,则流的顺序

当迭代同步的集合时,第一种方法将获得集合的锁一次,并在所有对action方法的调用中保持它,但对于流,它们使用集合的spliterator,它不锁定,并依赖于已经建立的不干扰规则。如果在迭代期间修改了支持流的集合,则会抛出ConcurrentModificationException或可能出现不一致的结果。

第四种方法(Parallel Stream.forEach)- 正如已经提到的,在并行流的情况下,不能保证尊重遇到的顺序。有可能在不同的线程中对不同的元素执行操作,而forEachOrdered绝不是这种情况

第五进路(Parallel Stream.forEachOrdered)- forEachOrdered将按照源指定的顺序处理元素,而不管流是顺序的还是并行的。所以在并行流中使用这个是没有意义的

或者你可以简单地使用Apache Commons实用程序:

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

我现在正好在做这个…

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

我也遇到过类似的问题。我的代码:

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循环

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

方法3:在java 8中打印列表

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

For循环输出列表的内容:

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

这取决于List中存储的对象类型,以及它是否有toString()方法的实现。System.out.println(list)应该打印所有标准java对象类型(StringLongInteger等)。在这种情况下,如果使用自定义对象类型,则需要自定义对象的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);
}
}
< p > String.join()使用 例如:< / p >
System.out.print(String.join("\n", list));

java 11问题的解决方案是:

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


System.out.println(toPrint);

你可以试试:

  • 2D(或更多)

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

  • < p > 1 d

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