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.

Author: gabuzo, 2012-04-12

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.

 53
Author: adarshr,
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())
 249
Author: Arkadiusz Cieśliński,
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));
 61
Author: Mark Wigmans,
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>
 25
Author: tbraun,
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)

 9
Author: Thamme Gowda,
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}
 9
Author: AlikElzin-kilaka,
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 "";
    }
    
 5
Author: MattG,
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: -)

 4
Author: parasietje,
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);
 4
Author: Nikita Koksharov,
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);
}
 2
Author: stones333,
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 Strings 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

 1
Author: Cratylus,
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.

 0
Author: Sirs,
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
 0
Author: Abdull,
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...),..}, ... }

 0
Author: user1485864,
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