159 votes

Impression d'une carte en Java

Je cherche une façon agréable d'imprimer une Map .

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

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

J'ai écrit ce petit bout 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 un moyen plus élégant et plus concis de le faire.

2 votes

Duplicata possible de Carte vers chaîne en Java parce que le format demandé ici et celui de System.out.println sont trop proches. Et si vous voulez quelque chose de personnalisé, cela se résume à "comment itérer sur une carte en Java" qui a certainement beaucoup d'autres réponses.

323voto

Arrays.toString(map.entrySet().toArray())

14 votes

Pas si bien si vous avez Map<String, Map<String,double[]>> alors vous aurez ce type de piqûre : [test={test=[D@3995ebd8, 2=[D@26fa5067, 3=[D@1d956d37, 4=[D@2cead81, 5=[D@14934d2b}...]

5 votes

Cela devrait être la réponse acceptée. Les tâches simples comme celle-ci ne devraient pas nécessiter de dépendance externe. Comme mentionné ci-dessus, les cartes plus complexes n'en bénéficient pas aussi facilement.

0 votes

Pas bon si vous avez une carte imbriquée

76voto

Mark Wigmans Points 111

Jetez un coup d'œil à la bibliothèque de Guava :

Joiner.MapJoiner mapJoiner = Joiner.on(",").withKeyValueSeparator("=");
System.out.println(mapJoiner.join(map));

65voto

adarshr Points 25912

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 placer cette logique dans une méthode utilitaire.

7 votes

C'est un anti-modèle, selon moi. Vous ajoutez une contrainte forte (l'héritage) à votre type, juste pour des avantages insignifiants (une belle impression). Vous feriez mieux d'utiliser une carte ordinaire, mais d'utiliser une méthode statique qui la prend comme argument.

44voto

tbraun Points 773

Les bibliothèques Apache à la rescousse !

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

Tout ce dont vous avez besoin est la bibliothèque Apache commons-collections ( lien avec le projet )

Les utilisateurs de 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>

0 votes

Cela ne permet pas de gérer les tableaux en tant que valeurs de la carte (ex. Map<String, String[]> ). Seuls leur className et leur hash sont imprimés au lieu des valeurs réelles.

0 votes

Ou log.debug("Carte : {}", MapUtils.toProperties(map)) ;

2 votes

MapUtils.verbosePrint est également très pratique, car il permet d'omettre le nom de la classe après chaque valeur émise par debugPrint.

4voto

parasietje Points 847

Regardez le code pour HashMap#toString() et AbstractMap#toString() dans les sources d'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é une façon plus élégante de le faire, il n'y en a pas :-)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X