Pretty-imprimer une carte en Java


Je cherche un bon moyen d'imprimer un Map.

map.toString() donne-moi: {key1=value1, key2=value2, key3=value3}

Je veux plus de liberté dans mes valeurs d'entrée de carte et je cherche quelque chose de plus comme ceci: key1="value1", key2="value2", key3="value3"

J'ai écrit ce petit morceau de code:

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

Mais je suis sûr qu'il existe une façon plus élégante et concise de le faire.

Author: gabuzo, 2012-04-12

14 answers

Ou mettez votre logique dans une petite classe bien rangée.

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

    }
}

Utilisation:

Map<String, String> myMap = new HashMap<String, String>();

System.out.println(new PrettyPrintingMap<String, String>(myMap));

Remarque: Vous pouvez également mettre cette logique dans une méthode utilitaire.

 53
Author: adarshr, 2012-04-12 08:57:13
Arrays.toString(map.entrySet().toArray())
 249
Author: Arkadiusz Cieśliński, 2013-10-28 15:35:22

Jetez un oeil à la bibliothèque de Goyave:

Joiner.MapJoiner mapJoiner = Joiner.on(",").withKeyValueSeparator("=");
System.out.println(mapJoiner.join(map));
 61
Author: Mark Wigmans, 2016-12-04 11:21:03

Les bibliothèques Apache à la rescousse!

MapUtils.debugPrint(System.out, "myMap", map);

Tout ce dont vous avez besoin Apache commons-collections library (project link )

Les utilisateurs Maven peuvent ajouter la bibliothèque en utilisant cette dépendance:

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>
 25
Author: tbraun, 2014-02-19 14:17:01

Quand j'ai org.json.JSONObject dans le classpath, je n':

Map<String, Object> stats = ...;
System.out.println(new JSONObject(stats).toString(2));

(cela indente magnifiquement les listes, les ensembles et les cartes qui peuvent être imbriqués)

 9
Author: Thamme Gowda, 2015-06-05 06:28:47

Simple et facile. Bienvenue dans le monde JSON. Utilisation de Gson de Google :

new Gson().toJson(map)

Exemple de carte avec 3 touches:

{"array":[null,"Some string"],"just string":"Yo","number":999}
 9
Author: AlikElzin-kilaka, 2016-02-21 06:31:56

Je préfère convertir la carte en une chaîne JSON c'est:

  • une norme
  • lisible par l'homme
  • pris en charge dans des éditeurs comme Sublime, VS Code, avec syntaxe mise en surbrillance, mise en forme et section masquer/afficher
  • prend en charge JPath afin que les éditeurs puissent signaler exactement quelle partie de l'objet vous avez navigué vers
  • Prend en charge les types complexes imbriqués dans l'objet

    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, 2017-10-13 18:48:07

Regardez le code pour HashMap#toString() et AbstractMap#toString() dans les sources 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(", ");
        }
    }
}

Donc, si les gars d'OpenJDK n'ont pas trouvé de moyen plus élégant de le faire, il n'y en a pas: -)

 4
Author: parasietje, 2012-04-12 09:05:56

Utilisation des flux Java 8:

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, 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, 2013-01-26 19:44:34

Vous devriez pouvoir faire ce que vous voulez en faisant:

System.out.println(map) par exemple

Tant que TOUS vos objets de la carte ont dépassé la méthode toString que vous verriez:
{key1=value1, key2=value2} de manière significative

Si c'est pour votre code, alors overiding toString est une bonne habitude et je vous suggère d'y aller à la place.

Pour votre exemple où vos objets sont String s, vous devriez aller bien sans rien d'autre.
C'est-à-dire que System.out.println(map) imprimerait exactement ce dont vous avez besoin sans aucun code supplémentaire

 1
Author: Cratylus, 2012-04-12 08:52:35

Je suppose que quelque chose comme ça serait plus propre et vous offrirait plus de flexibilité avec le format de sortie (changez simplement de modèle):

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

Je sais que devoir supprimer la dernière virgule est moche, mais je pense que c'est plus propre que des alternatives comme celle dans cette solution ou manuellement en utilisant un itérateur.

 0
Author: Sirs, 2017-05-23 10:31:38

En tant que solution rapide et sale tirant parti de l'infrastructure existante, vous pouvez envelopper votre uglyPrintedMap dans un java.util.HashMap, puis utiliser 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, 2013-09-26 10:47:02

Ne répond pas exactement à la question, mais il convient de mentionner Lombodok @ToString annotation . Si vous annotez avec @ToString les classes key / value, alors faire System.out.println(map) retournera quelque chose de significatif.

, Il fonctionne aussi très bien avec des cartes de cartes, par exemple: Map<MyKeyClass, Map<String, MyValueClass>> sera imprimé comme

{MyKeyClass(properties...)={string1=MyValuesClass(properties...), string2=MyValuesCalss(properties...),..}, ... }

 0
Author: user1485864, 2018-09-07 08:22:46