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

澄清一下,我说的是Java的内置集合,所以我不能重写它的toString()。

我怎样才能得到一个漂亮的可打印版本的堆栈?


当前回答

对于Apache Commons 3,您希望调用

StringUtils.join(myCollection, ",")

其他回答

有两种方法可以简化工作。 1. 导入Gson库。 2. 使用Lombok。

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

我放了一个关于Gson prettyPrint的例子,我创建了一个helper类来打印对象和对象的集合。如果使用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(","));
   }

}

在Collection上调用Sop时要小心,它会抛出ConcurrentModification Exception。因为每个集合的内部toString方法在内部调用集合上的迭代器。

由Apache Commons项目提供的MapUtils类提供了一个MapUtils. debugprint方法,它将漂亮地打印你的地图。

现在在java (Java7/8)中,大多数集合都有一个有用的toString()。 所以不需要做流操作来连接你需要的东西,只需要在集合中重写你的值类的toString,你就可以得到你需要的东西。

AbstractMap和AbstractCollection都通过对每个元素调用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 }}
  }
}

更新Java 14(2020年3月)

记录现在是一个预览功能,如果类只保存数据,则不需要重写toString()。记录实现了一个数据契约,为您的方便提供了对字段的公共只读访问,并实现了默认函数,如比较,toString和hashcode。

所以一旦可以实现Foo的行为如下:

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

public class ToString {
  static record Foo(int i) { }
  
  public static void main(String[] args) {
    Foo f = new Foo(10);
    System.out.println(f.toString());
    // prints: Foo[i=10]

    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: [Foo[i=10], Foo[i=12], Foo[i=13], Foo[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=Foo[i=10], 12=Foo[i=12], 13=Foo[i=13], 14=Foo[i=14]}
  }
}

JSON

另一种解决方案是将您的集合转换为JSON格式并打印JSON - string。其优点是格式良好且可读的Object-String,而不需要实现toString()。

使用谷歌的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);
}