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

发布于 2024-07-10 16:37:08 字数 251 浏览 7 评论 0原文

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

只是为了澄清一下,我正在谈论 Java 的内置集合,因此我无法重写其 toString()

如何获得堆栈的精美可打印版本?

I wish to print a Stack<Integer> object as nicely as the Eclipse debugger does (i.e. [1,2,3...]) but printing it with out = "output:" + stack doesn't return this nice result.

Just to clarify, I'm talking about Java's built-in collection so I can't override its toString().

How can I get a nice printable version of the stack?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(20

悟红尘 2024-07-17 16:37:08

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

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

You could convert it to an array and then print that out with Arrays.toString(Object[]):

System.out.println(Arrays.toString(stack.toArray()));
一个人的旅程 2024-07-17 16:37:08
String.join(",", yourIterable);

(Java 8)

String.join(",", yourIterable);

(Java 8)

总攻大人 2024-07-17 16:37:08

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

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

首先我们使用 mapObject::toString 来创建 Collection,然后使用连接收集器以 , 作为分隔符连接集合中的每个项目。

With java 8 streams and collectors it can be done easily:

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

first we use map with Object::toString to create Collection<String> and then use joining collector to join every item in collection with , as delimiter.

真心难拥有 2024-07-17 16:37:08

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

The MapUtils class offered by the Apache Commons project offers a MapUtils.debugPrint method which will pretty print your map.

浮云落日 2024-07-17 16:37:08

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

Iterables.toString(myIterable)

Guava looks like a good option:

Iterables.toString(myIterable)

北恋 2024-07-17 16:37:08

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

System.out.println(Collection c) already print any type of collection in readable format. Only if collection contains user defined objects , then you need to implement toString() in user defined class to display content.

梦罢 2024-07-17 16:37:08

在类上实现 toString()。

我推荐 Apache Commons ToStringBuilder 使这变得更容易。 有了它,您只需编写这种方法:

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

为了获得这种输出:

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

还有一个 反射实现

Implement toString() on the class.

I recommend the Apache Commons ToStringBuilder to make this easier. With it, you just have to write this sort of method:

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

In order to get this sort of output:

Person@7f54[name=Stephen,age=29]

There is also a reflective implementation.

冰雪梦之恋 2024-07-17 16:37:08

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

}

这不是一个完整的实现,而只是一个开始。

I agree with the above comments about overriding toString() on your own classes (and about automating that process as much as possible).

For classes you didn't define, you could write a ToStringHelper class with an overloaded method for each library class you want to have handled to your own tastes:

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

EDIT: Responding to the comment by xukxpvfzflbbld, here's a possible implementation for the cases mentioned previously.

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

}

This isn't a full-blown implementation, but just a starter.

孤独陪着我 2024-07-17 16:37:08

您可以使用 JAVA 中的“Objects”类(自 1.7 起可用)

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

输出:1273, 123, 876, 897

另一种可能性是使用 Google Guave 中的“MoreObjects”类< /strong>,它提供了许多有用的辅助函数:

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

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

番石榴文档

You can use the "Objects" class from JAVA (which is available since 1.7)

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

Output: 1273, 123, 876, 897

Another possibility is to use the "MoreObjects" class from Google Guave, which provides many of useful helper functions:

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

Output:
NameOfYourObject=[1273, 123, 876, 897]

Guava docs

蓦然回首 2024-07-17 16:37:08

使用Apache Commons 3,您想要调用

StringUtils.join(myCollection, ",")

With Apache Commons 3, you want to call

StringUtils.join(myCollection, ",")
雾里花 2024-07-17 16:37:08

在Java8

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

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

In Java8

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

or

//to print with commas
stack.forEach(
    (ele) -> {
        System.out.print(ele + ",");
    }
);
稳稳的幸福 2024-07-17 16:37:08

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

AbstractMap 和 < a href="https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html#toString--" rel="nofollow noreferrer">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]}
  }
}

most collections have a useful toString() in java these days (Java7/8).
So there is no need to do stream operations to concatenate what you need, just override toString of your value class in the collection and you get what you need.

both AbstractMap and AbstractCollection implement toString() by calling toString per element.

below is a testclass to show behaviour.

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

Update Java 14 (Mar 2020)

Records are now a preview feature not requiring you to override toString() if your class only holds data. Records implement a data contract, giving public readonly access to it's fields and implementing default functions for your convience, like comparison, toString and hashcode.

so once could implement Foo as follows with the behavior:

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]}
  }
}
叶落知秋 2024-07-17 16:37:08

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

Newer JDK already has AbstractCollection.toString() implemented, and Stack extends AbstractCollection so you just have to call toString() on your collection:

    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(' ');
        }
    }
天暗了我发光 2024-07-17 16:37:08

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

If this is your own collection class rather than a built in one, you need to override its toString method. Eclipse calls that function for any objects for which it does not have a hard-wired formatting.

鼻尖触碰 2024-07-17 16:37:08

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

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

}

Just Modified the previous example to print even collection containing user defined objects.

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

}
梦境 2024-07-17 16:37:08

在 Collection 上调用 Sop 时要小心,它可能会抛出 ConcurrentModification 异常。 因为每个 Collection 的内部 toString 方法内部都会调用 Collection 上的 Iterator

Be careful when calling Sop on Collection, it can throw ConcurrentModification Exception. Because internally toString method of each Collection internally calls Iterator over the Collection.

岁月流歌 2024-07-17 16:37:08

应该适用于除 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();
}

Should work for any collection except Map, but it's easy to support, too.
Modify code to pass these 3 chars as arguments if needed.

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();
}
萌梦深 2024-07-17 16:37:08

您可以尝试使用

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

You can try using

org.apache.commons.lang3.builder.ToStringBuilder.reflectionToString(yourCollection);
怪我太投入 2024-07-17 16:37:08

有两种方法可以简化您的工作。
1.导入Gson库。
2.使用龙目岛。

它们都可以帮助您从对象实例创建字符串。 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(","));
   }

}

There are two ways you could simplify your work.
1. import Gson library.
2. use Lombok.

Both of them help you create String from object instance. Gson will parse your object, lombok will override your class object toString method.

I put an example about Gson prettyPrint, I create helper class to print object and collection of objects. If you are using lombok, you could mark your class as @ToString and print your object directly.

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

}

假面具 2024-07-17 16:37:08

JSON

另一种解决方案可以将您的集合转换为 JSON 格式并打印Json 字符串。 优点是格式良好且可读的对象字符串,无需实现 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);
}

JSON

An alternative Solution could be converting your collection in the JSON format and print the Json-String. The advantage is a well formatted and readable Object-String without a need of implementing the toString().

Example using Google's 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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文