很好地打印Java集合(toString不会返回漂亮的输出)


211

我希望Stack<Integer>像Eclipse调试器一样出色地打印对象(即[1,2,3...]),但是使用进行打印out = "output:" + stack不会返回该效果。

为了澄清起见,我正在谈论Java的内置集合,因此我无法覆盖它toString()

我如何获得堆叠的漂亮可打印版本?


7
至少从Java 7开始AbstractCollection@toString(因此String + Stack),它已经可以按您的需要进行打印了。
西罗Santilli郝海东冠状病六四事件法轮功

Answers:


317

您可以将其转换为数组,然后使用Arrays.toString(Object[])以下命令将其打印出来:

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

11
我喜欢。简单,干净。说实话,Collections也需要一个toString方法,但这也可以。
Tovi7 2011年

1
@ Tovi7可能不是因为大多数OOTB集合已经提供了可读的toString(),而数组却没有。
Max Nanasy

@Boosha还需要O(n)时间将堆栈转换为字符串,并花费O(n)时间将字符串打印至控制台
Zach Langley

stack.toArray()在CPU,时间和内存方面可能会非常昂贵。迭代原始集合/可迭代对象的解决方案可能会减少资源消耗。
AlikElzin-kilaka,

52
String.join(",", yourIterable);

(Java 8)


12
yourIterable必须是Iterable <?扩展CharSequence>
Nathan

3
String.join(“,”,yourCollection.stream()。map(o-> o.toString())。collect(Collectors.toList()))
user1016765 2016年

@ user1016765 yourCollection.stream().map( o -> o.toString() ).collect( joining(",") ))更好,因为您从左到右阅读它,您无需回头看看大脑中中间列表的内容
cdalxndr

18

使用Java 8流和收集器,可以轻松完成:

String format(Collection<?> c) {
  String s = c.stream().map(Object::toString).collect(Collectors.joining(","));
  return String.format("[%s]", s);
}

首先,我们使用mapwith Object::toString进行创建Collection<String>,然后使用joining collector将,作为分隔符的collection中的每个项目进行联接。


22
我不得不忍住不要从答案中删除“轻松”一词;-) Collections.toString(stack)很容易。
FrVaBe 2014年

为什么要调用String.format()?只是为了获得方括号?
Jolta


12

System.out.println(Collection c)已经以可读格式打印任何类型的集合。仅当collection包含用户定义的对象时,才需要在用户定义的类中实现toString()来显示内容。


12

在类上实现toString()。

我建议使用Apache Commons ToStringBuilder使其更容易。使用它,您只需要编写这种方法即可:

public String toString() {
     return new ToStringBuilder(this).
       append("name", name).
       append("age", age).
       toString(); 
}

为了获得这种输出:

Person @ 7f54 [姓名=斯蒂芬,年龄= 29]

还有一个反思性的实现


ToStringBuilder通常更适用于承载信息的bean和对象,而不适用于复杂的数据结构。如果堆栈对象未打印所有存储的项目,则无济于事。
Uri

2
反射ToStringBuilder,HashCodeBuilder和EqualsBuilder的使用具有很高的感染力。尽管输出没问题,但是这些课程几乎不是一周的表演高峰…
Jan Hruby 2012年

2
问题明确指出该类是内置集合,因此无法修改toString()。
Rasmus Kaj


9

我同意以上有关toString()在您自己的类上进行重写(以及尽可能使该过程自动化)的评论。

对于你的类没有定义,你可以写一个ToStringHelper类你希望有处理,以自己的口味各库类的重载的方法:

public class ToStringHelper {
    //... instance configuration here (e.g. punctuation, etc.)
    public toString(List m) {
        // presentation of List content to your liking
    }
    public toString(Map m) {
        // presentation of Map content to your liking
    }
    public toString(Set m) {
        // presentation of Set content to your liking
    }
    //... etc.
}

编辑:响应xukxpvfzflbbld的评论,这是前面提到的情况的可能实现。

package com.so.demos;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class ToStringHelper {

    private String separator;
    private String arrow;

    public ToStringHelper(String separator, String arrow) {
        this.separator = separator;
        this.arrow = arrow;
    }

   public String toString(List<?> l) {
        StringBuilder sb = new StringBuilder("(");
        String sep = "";
        for (Object object : l) {
            sb.append(sep).append(object.toString());
            sep = separator;
        }
        return sb.append(")").toString();
    }

    public String toString(Map<?,?> m) {
        StringBuilder sb = new StringBuilder("[");
        String sep = "";
        for (Object object : m.keySet()) {
            sb.append(sep)
              .append(object.toString())
              .append(arrow)
              .append(m.get(object).toString());
            sep = separator;
        }
        return sb.append("]").toString();
    }

    public String toString(Set<?> s) {
        StringBuilder sb = new StringBuilder("{");
        String sep = "";
        for (Object object : s) {
            sb.append(sep).append(object.toString());
            sep = separator;
        }
        return sb.append("}").toString();
    }

}

这不是一个成熟的实现,而只是一个入门。


7

您可以使用JAVA中“ Objects”类(从1.7开始可用)

Collection<String> myCollection = Arrays.asList("1273","123","876","897");
Objects.toString(myCollection);

输出:1273、123、876、897

另一种可能性是使用Google Guave“ MoreObjects”类,该类提供了许多有用的帮助程序功能:

MoreObjects.toStringHelper(this).add("NameOfYourObject", myCollection).toString());

输出:NameOfYourObject = [1273,123,876,897]

番石榴文件


1
Objects.toString()只是呼吁toString()集合。在您的示例中,这可行,因为大概toString()在支持数组的集合上恰好可以很好地打印。
GuyPaddock

3

使用Apache Commons 3时,您要调用

StringUtils.join(myCollection, ",")

3

在Java8中

//will prints each element line by line
stack.forEach(System.out::println);

要么

//to print with commas
stack.forEach(
    (ele) -> {
        System.out.print(ele + ",");
    }
);

1

只是修改了前面的示例,以打印甚至包含用户定义对象的集合。

public class ToStringHelper {

    private  static String separator = "\n";

    public ToStringHelper(String seperator) {
        super();
        ToStringHelper.separator = seperator;

    }

    public  static String toString(List<?> l) {
        StringBuilder sb = new StringBuilder();
        String sep = "";
        for (Object object : l) {
            String v = ToStringBuilder.reflectionToString(object);
            int start = v.indexOf("[");
            int end = v.indexOf("]");
            String st =  v.substring(start,end+1);
            sb.append(sep).append(st);
            sep = separator;
        }
        return sb.toString();
    }

    public static String toString(Map<?,?> m) {
        StringBuilder sb = new StringBuilder();
        String sep = "";
        for (Object object : m.keySet()) {
            String v = ToStringBuilder.reflectionToString(m.get(object));
            int start = v.indexOf("[");
            int end = v.indexOf("]");
            String st =  v.substring(start,end+1);
            sb.append(sep).append(st);
            sep = separator;
        }
        return sb.toString();
    }

    public static String toString(Set<?> s) {
        StringBuilder sb = new StringBuilder();
        String sep = "";
        for (Object object : s) {
            String v = ToStringBuilder.reflectionToString(object);
            int start = v.indexOf("[");
            int end = v.indexOf("]");
            String st =  v.substring(start,end+1);
            sb.append(sep).append(st);
            sep = separator;
        }
        return sb.toString();
    }

    public static void print(List<?> l) {
        System.out.println(toString(l));    
    }
    public static void print(Map<?,?> m) {
        System.out.println(toString(m));    
    }
    public static void print(Set<?> s) {
        System.out.println(toString(s));    
    }

}

1

toString()如今,大多数集合在Java中都非常有用(Java7 / 8)。因此,无需进行流操作来连接所需的内容,只需覆盖toString集合中的值类即可获得所需的内容。

AbstractMapAbstractCollection都通过对每个元素调用toString来实现toString()。

下面是显示行为的测试类。

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

public class ToString {
  static class Foo {
    int i;
    public Foo(int i) { this.i=i; }
    @Override
    public String toString() {
        return "{ i: " + i + " }";
    }
  }
  public static void main(String[] args) {
    List<Foo> foo = new ArrayList<>();
    foo.add(new Foo(10));
    foo.add(new Foo(12));
    foo.add(new Foo(13));
    foo.add(new Foo(14));
    System.out.println(foo.toString());
    // prints: [{ i: 10 }, { i: 12 }, { i: 13 }, { i: 14 }]

    Map<Integer, Foo> foo2 = new HashMap<>();
    foo2.put(10, new Foo(10));
    foo2.put(12, new Foo(12));
    foo2.put(13, new Foo(13));
    foo2.put(14, new Foo(14));
    System.out.println(foo2.toString());
    // prints: {10={ i: 10 }, 12={ i: 12 }, 13={ i: 13 }, 14={ i: 14 }}
  }
}

1

JSON格式

另一种解决方案可能是将您的集合转换为JSON格式并打印Json-String。优点是格式正确且易于阅读的Object-String,而无需实现toString()

使用Google的Gson的示例:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

...

    printJsonString(stack);

...
public static void printJsonString(Object o) {
    GsonBuilder gsonBuilder = new GsonBuilder();
    /*
     * Some options for GsonBuilder like setting dateformat or pretty printing
     */
    Gson gson = gsonBuilder.create();
    String json= gson.toJson(o);
    System.out.println(json);
}

0

如果这是您自己的集合类,而不是内置类,则需要重写其toString方法。Eclipse为没有硬连线格式的任何对象调用该函数。


eclipse如何用硬连线格式格式化那些类?这就是我想要的。
Elazar Leibovich

0

在Collection上调用Sop时要小心,它可能引发ConcurrentModificationException。因为toString每个Collection的内部方法都会在内部调用IteratorCollection。


0

应该适用于除以外的任何集合Map,但是也很容易支持。如果需要,修改代码以将这三个字符作为参数传递。

static <T> String seqToString(Iterable<T> items) {
    StringBuilder sb = new StringBuilder();
    sb.append('[');
    boolean needSeparator = false;
    for (T x : items) {
        if (needSeparator)
            sb.append(' ');
        sb.append(x.toString());
        needSeparator = true;
    }
    sb.append(']');
    return sb.toString();
}

0

您可以尝试使用

org.apache.commons.lang3.builder.ToStringBuilder.reflectionToString(yourCollection);

0

您可以通过两种方式简化工作。1.导入Gson库。2.使用龙目岛。

它们都可以帮助您从对象实例创建String。Gson将解析您的对象,而lombok将覆盖您的类对象的toString方法。

我举了一个关于Gson prettyPrint的示例,我创建了一个帮助器类来打印对象和对象集合。如果使用的是lombok,则可以将类标记为@ToString并直接打印对象。

@Scope(value = "prototype")
@Component
public class DebugPrint<T> {
   public String PrettyPrint(T obj){
      Gson gson = new GsonBuilder().setPrettyPrinting().create();
      return gson.toJson(obj);
   }
   public String PrettyPrint(Collection<T> list){
      Gson gson = new GsonBuilder().setPrettyPrinting().create();
      return list.stream().map(gson::toJson).collect(Collectors.joining(","));
   }

}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.