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

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

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


当前回答

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

其他回答

我同意上面关于在您自己的类上重写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();
    }

}

这不是一个成熟的实现,而只是一个开始。

你可以使用JAVA中的“Objects”类(从1.7开始就有了)

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

输出:1273,123,876,897

另一种可能是使用谷歌Guave中的"MoreObjects"类,它提供了许多有用的帮助函数:

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

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

番石榴文档

现在在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]}
  }
}

更新的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(' ');
        }
    }

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

Iterables.toString (myIterable)