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

时间:2008-12-27 20:55:20

标签: java debugging pretty-print

我希望像Eclipse调试器一样打印Stack<Integer>对象(即[1,2,3...]),但是用out = "output:" + stack打印它不会返回这个好结果。

为了澄清,我在谈论Java的内置集合,所以我不能覆盖它的toString()

如何获得一个漂亮的可打印版本的堆栈?

20 个答案:

答案 0 :(得分:295)

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

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

答案 1 :(得分:46)

String.join(",", yourIterable);

(Java 8)

答案 2 :(得分:18)

Apache Commons项目提供的MapUtils类提供了一个MapUtils.debugPrint方法,可以很好地打印您的地图。

答案 3 :(得分:15)

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

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

首先我们使用mapObject::toString创建Collection<String>,然后使用加入收集器将,作为分隔符加入集合中的每个项目。

答案 4 :(得分:12)

在类上实现toString()。

我建议Apache Commons ToStringBuilder使这更容易。有了它,你只需要编写这种方法:

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

为了获得这种输出:

  

人@ 7f54 [名称=斯蒂芬,年龄= 29]

还有reflective implementation

答案 5 :(得分:10)

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

答案 6 :(得分: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 :(得分:9)

番石榴看起来是个不错的选择:

Iterables.toString(myIterable)

答案 8 :(得分:5)

您可以使用&#34; Objects&#34;来自JAVA的课程(自1.7以来可用)

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

输出:1273,123,876,897

另一种可能性是使用&#34; MoreObjects&#34;来自Google Guave的课程,它提供了许多有用的辅助函数:

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

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

Guava docs

答案 9 :(得分:3)

使用 Apache Commons 3 ,您需要致电

StringUtils.join(myCollection, ",")

答案 10 :(得分:2)

在Java8中

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

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

答案 11 :(得分: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));    
    }

}

答案 12 :(得分: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);
}

答案 13 :(得分:1)

最近(Java7 / 8),大多数集合在Java中都有一个有用的toString()。 因此,无需进行流操作来连接所需的内容,只需覆盖集合中值类的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 }}
  }
}

答案 14 :(得分:0)

较新的 JDK 已经实现了 AbstractCollection.toString(),并且 Stack 扩展了 AbstractCollection,因此您只需在您的集合上调用 toString()

    public abstract class AbstractCollection<E> implements Collection<E> {
    ...
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";
    
        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

答案 15 :(得分: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(","));
   }

}

答案 16 :(得分:0)

您可以尝试使用

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

答案 17 :(得分:0)

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

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

答案 18 :(得分:0)

在调用Sop on Collection时要小心,它会抛出ConcurrentModification异常。因为每个Collection的内部toString方法在内部调用Iterator而不是Collection。

答案 19 :(得分:0)

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