Last active
July 17, 2019 15:08
-
-
Save SadiinsoSnowfall/e4dd4366bf8f403ca298a4869d0b7029 to your computer and use it in GitHub Desktop.
Functions to get the String representation of any Java Object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* After some benchmarking with JMH, I found that the best way to implement the part that manage maps and collections was | |
* to use an Iterator and its built-in function that take a lambda (forEachRemaning). | |
* List of others solutions I tried: | |
* - Iterator (using for...in loop) | |
* - Iterator + while loop | |
* - Spliterator + Stream | |
* - Spliterator + lambda | |
*/ | |
public class DeepToString { | |
/** | |
* | |
* @param o The object to scan | |
* @return A string representation of {@code o} | |
* @see #deepToString(Object, boolean) | |
*/ | |
public static String deepToString(Object o) { | |
return deepToString(o, true); | |
} | |
/** | |
* | |
* @param o The object to scan | |
* @param preventLoop Whether or not to prevent reference loops when scanning the object | |
* @return A string representation of {@code o} | |
* @see #deepToString(Object) | |
*/ | |
public static String deepToString(Object o, boolean preventLoop) { | |
if (o == null) { | |
return "null"; | |
} | |
StringBuilder buf = new StringBuilder(64); | |
deepToString(o, buf, (preventLoop ? new HashSet<>() : null)); | |
return buf.toString(); | |
} | |
/** | |
* Internal function, scan an object and get its string representation | |
* @param o An object to scan | |
* @param buf A String buffer to prevent high alloc count | |
* @param dejaVu A Set of object already scanned to prevent reference loop | |
*/ | |
private static void deepToString(Object o, StringBuilder buf, Set<Object> dejaVu) { | |
if (o == null) { | |
buf.append("null"); | |
return; | |
} | |
if(dejaVu != null) { | |
if (dejaVu.contains(o)) { | |
buf.append("[...]"); | |
return; | |
} | |
dejaVu.add(o); | |
} | |
Class<?> clazz = o.getClass(); | |
if (clazz.isArray()) { | |
if (clazz == byte[].class) { | |
buf.append(Arrays.toString((byte[]) o)); | |
} else if (clazz == short[].class) { | |
buf.append(Arrays.toString((short[]) o)); | |
} else if (clazz == int[].class) { | |
buf.append(Arrays.toString((int[]) o)); | |
} else if (clazz == long[].class) { | |
buf.append(Arrays.toString((long[]) o)); | |
} else if (clazz == char[].class) { | |
buf.append(Arrays.toString((char[]) o)); | |
} else if (clazz == float[].class) { | |
buf.append(Arrays.toString((float[]) o)); | |
} else if (clazz == double[].class) { | |
buf.append(Arrays.toString((double[]) o)); | |
} else if (clazz == boolean[].class) { | |
buf.append(Arrays.toString((boolean[]) o)); | |
} else { // element is an array of object references | |
Object[] objs = (Object[]) o; | |
if(objs.length == 0) { | |
buf.append("[]"); | |
} else { | |
int last = objs.length - 1; | |
buf.append('['); | |
for (int t = 0; t < last; t++) { | |
deepToString(objs[t], buf, dejaVu); | |
buf.append(", "); | |
} | |
deepToString(objs[last], buf, dejaVu); | |
buf.append(']'); | |
} | |
} | |
} else if (o instanceof Map) { | |
Iterator<Map.Entry<?, ?>> iter = ((Set<Map.Entry<?, ?>>) ((Map) o).entrySet()).iterator(); | |
if(iter.hasNext()) { | |
buf.append('{'); | |
Map.Entry<?, ? > first = iter.next(); | |
deepToString(first.getKey(), buf, dejaVu); | |
buf.append("->"); | |
deepToString(first.getValue(), buf, dejaVu); | |
iter.forEachRemaining(entry -> { | |
buf.append(", "); | |
deepToString(entry.getKey(), buf, dejaVu); | |
buf.append("->"); | |
deepToString(entry.getValue(), buf, dejaVu); | |
}); | |
buf.append('}'); | |
} else { | |
buf.append("{}"); | |
} | |
} else if (o instanceof Collection) { | |
Iterator<Object> iter = ((Collection) o).iterator(); | |
if(iter.hasNext()) { | |
buf.append('('); | |
deepToString(iter.next(), buf, dejaVu); | |
iter.forEachRemaining(elem -> { | |
buf.append(", "); | |
deepToString(elem, buf, dejaVu); | |
}); | |
buf.append(')'); | |
} else { | |
buf.append("()"); | |
} | |
} else if (o instanceof String) { | |
buf.append('\"').append((String) o).append('\"'); | |
} else if (clazz == Object.class) { | |
buf.append("obj"); | |
} else { | |
buf.append(o.toString()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment