Pretty-imprimir un mapa en Java
Estoy buscando una buena manera de pretty-print a Map
.
map.toString()
me da: {key1=value1, key2=value2, key3=value3}
Quiero más libertad en los valores de entrada de mi mapa y estoy buscando algo más como esto: key1="value1", key2="value2", key3="value3"
Escribí este pequeño fragmento de código:
StringBuilder sb = new StringBuilder();
Iterator<Entry<String, String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Entry<String, String> entry = iter.next();
sb.append(entry.getKey());
sb.append('=').append('"');
sb.append(entry.getValue());
sb.append('"');
if (iter.hasNext()) {
sb.append(',').append(' ');
}
}
return sb.toString();
Pero estoy seguro de que hay una manera más elegante y concisa de hacer esto.
14 answers
O poner su lógica en una pequeña clase ordenada.
public class PrettyPrintingMap<K, V> {
private Map<K, V> map;
public PrettyPrintingMap(Map<K, V> map) {
this.map = map;
}
public String toString() {
StringBuilder sb = new StringBuilder();
Iterator<Entry<K, V>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Entry<K, V> entry = iter.next();
sb.append(entry.getKey());
sb.append('=').append('"');
sb.append(entry.getValue());
sb.append('"');
if (iter.hasNext()) {
sb.append(',').append(' ');
}
}
return sb.toString();
}
}
Uso:
Map<String, String> myMap = new HashMap<String, String>();
System.out.println(new PrettyPrintingMap<String, String>(myMap));
Nota: También puede poner esa lógica en un método de utilidad.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-12 08:57:13
Arrays.toString(map.entrySet().toArray())
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-28 15:35:22
Echa un vistazo a la biblioteca de Guayaba:
Joiner.MapJoiner mapJoiner = Joiner.on(",").withKeyValueSeparator("=");
System.out.println(mapJoiner.join(map));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-04 11:21:03
¡Bibliotecas Apache al rescate!
MapUtils.debugPrint(System.out, "myMap", map);
Todo lo que necesita Apache commons-collections library (project link)
Los usuarios de Maven pueden agregar la biblioteca usando esta dependencia:
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-19 14:17:01
Cuando tengo org.json.JSONObject
en el classpath, hago:
Map<String, Object> stats = ...;
System.out.println(new JSONObject(stats).toString(2));
(esto sangra maravillosamente listas, conjuntos y mapas que pueden anidarse)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-05 06:28:47
Simple y fácil. Bienvenido al mundo JSON. Usando el Gson de Google :
new Gson().toJson(map)
Ejemplo de mapa con 3 teclas:
{"array":[null,"Some string"],"just string":"Yo","number":999}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-21 06:31:56
Prefiero convertir el mapa a una cadena JSON que es:
- un estándar
- legible por humanos
- compatible con editores como Sublime, VS Code, con sintaxis resaltado, formato y sección hide/show
- soporta JPath para que los editores puedan informar exactamente qué parte del objeto usted ha navegado a
-
Soporta tipos complejos anidados dentro del objeto
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; public static String getAsFormattedJsonString(Object object) { ObjectMapper mapper = new ObjectMapper(); try { return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object); } catch (JsonProcessingException e) { e.printStackTrace(); } return ""; }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-13 18:48:07
Mira el código para HashMap#toString()
y AbstractMap#toString()
en las fuentes de OpenJDK:
class java.util.HashMap.Entry<K,V> implements Map.Entry<K,V> {
public final String toString() {
return getKey() + "=" + getValue();
}
}
class java.util.AbstractMap<K,V> {
public String toString() {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (! i.hasNext())
return "{}";
StringBuilder sb = new StringBuilder();
sb.append('{');
for (;;) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
sb.append(key == this ? "(this Map)" : key);
sb.append('=');
sb.append(value == this ? "(this Map)" : value);
if (! i.hasNext())
return sb.append('}').toString();
sb.append(", ");
}
}
}
Así que si los chicos de OpenJDK no encontraron una manera más elegante de hacer esto, no hay ninguna: -)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-12 09:05:56
Usando Java 8 Streams:
Map<Object, Object> map = new HashMap<>();
String content = map.entrySet()
.stream()
.map(e -> e.getKey() + "=\"" + e.getValue() + "\"")
.collect(Collectors.joining(", "));
System.out.println(content);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-14 16:32:55
public void printMapV2 (Map <?, ?> map) {
StringBuilder sb = new StringBuilder(128);
sb.append("{");
for (Map.Entry<?,?> entry : map.entrySet()) {
if (sb.length()>1) {
sb.append(", ");
}
sb.append(entry.getKey()).append("=").append(entry.getValue());
}
sb.append("}");
System.out.println(sb);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-26 19:44:34
Usted debe ser capaz de hacer lo que quiere haciendo:
System.out.println(map)
por ejemplo
Siempre y cuando TODOS sus objetos en el mapa tengan overiden el método toString
que verá:{key1=value1, key2=value2}
de una manera significativa
Si esto es para su código, entonces overiding toString
es un buen hábito y le sugiero que vaya por eso en su lugar.
Para su ejemplo donde sus objetos son String
s usted debe estar bien sin nada más.
Es decir, System.out.println(map)
imprimiría exactamente lo que necesita sin ningún código adicional
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-12 08:52:35
Supongo que algo como esto sería más limpio y le proporcionaría más flexibilidad con el formato de salida (simplemente cambie la plantilla):
String template = "%s=\"%s\",";
StringBuilder sb = new StringBuilder();
for (Entry e : map.entrySet()) {
sb.append(String.format(template, e.getKey(), e.getValue()));
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1); // Ugly way to remove the last comma
}
return sb.toString();
Sé que tener que eliminar la última coma es feo, pero creo que es más limpio que alternativas como la en esta solución o manualmente usando un iterador.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:38
Como una solución rápida y sucia que aprovecha la infraestructura existente, puede envolver su uglyPrintedMap
en un java.util.HashMap
, luego usar toString()
.
uglyPrintedMap.toString(); // ugly
System.out.println( uglyPrintedMap ); // prints in an ugly manner
new HashMap<Object, Object>(jobDataMap).toString(); // pretty
System.out.println( new HashMap<Object, Object>(uglyPrintedMap) ); // prints in a pretty manner
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-26 10:47:02
No responde exactamente a la pregunta, pero vale la pena mencionar Lombodok @ToString
anotación . Si anota con @ToString
las clases key / value
, entonces hacer System.out.println(map)
devolverá algo significativo.
También funciona muy bien con mapas de mapas, por ejemplo:
Map<MyKeyClass, Map<String, MyValueClass>>
se imprimirá como
{MyKeyClass(properties...)={string1=MyValuesClass(properties...), string2=MyValuesCalss(properties...),..},
...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-07 08:22:46