问题
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?
回答1:
You could convert it to an array and then print that out with Arrays.toString(Object[])
:
System.out.println(Arrays.toString(stack.toArray()));
回答2:
String.join(",", yourIterable);
(Java 8)
回答3:
The MapUtils class offered by the Apache Commons project offers a MapUtils.debugPrint
method which will pretty print your map.
回答4:
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.
回答5:
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.
回答6:
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.
回答7:
Guava looks like a good option:
Iterables.toString(myIterable)
回答8:
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.
回答9:
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
回答10:
With Apache Commons 3, you want to call
StringUtils.join(myCollection, ",")
回答11:
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 + ",");
}
);
回答12:
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));
}
}
回答13:
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 }}
}
}
回答14:
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.
回答15:
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.
回答16:
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();
}
回答17:
You can try using
org.apache.commons.lang3.builder.ToStringBuilder.reflectionToString(yourCollection);
来源:https://stackoverflow.com/questions/395401/printing-java-collections-nicely-tostring-doesnt-return-pretty-output