2012-04-12 11 views
94

Sto cercando un modo carino per stampare un Map.Pretty-print una mappa in Java

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

voglio più libertà nelle mie mappa valori di ingresso e sono alla ricerca di qualcosa di più simile a questo: key1="value1", key2="value2", key3="value3"

ho scritto questo piccolo pezzo di codice:

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

Ma sono sicuro che c'è un modo più elegante e conciso per farlo.

+1

possibile duplicato di [Mappa per stringa in Java] (http://stackoverflow.com/questions/2828252/map-to-string-in-java) perché il formato richiesto qui e quello di 'System.out.println' sono troppo vicini. E se vuoi qualcosa di personalizzato, questo si riduce a "come iterare su una mappa in Java" che ha sicuramente molte altre risposte. –

risposta

50

Oppure metti la tua logica in una piccola classe ordinata.

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

    } 
} 

Usage:

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

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

Nota: Si può anche mettere che la logica in un metodo di utilità.

1

Si dovrebbe essere in grado di fare quello che vuoi facendo:

System.out.println(map) ad esempio

a condizione che tutti gli oggetti nella mappa hanno overiden il metodo toString si dovrebbe vedere:
{key1=value1, key2=value2} in un significato significativo

Se questo è per il tuo codice, allora l'overiding toString è una buona abitudine e ti suggerisco di farlo.

Per il tuo esempio in cui gli oggetti sono String si dovrebbe andare bene senza nient'altro.
I.e. System.out.println(map) stamperà esattamente ciò che ti serve senza alcun codice aggiuntivo

+1

le sue chiavi e valori sono stringhe; Penso che abbia ottenuto il metodo toString coperto da tbh. – Tom

+0

Hai ragione, ma forse ha copiato un esempio banale per formulare il suo punto. Ma io aggiorno la risposta – Cratylus

+0

Sì, avrei dovuto indicare che la mia mappa è Map . Ma ho anche indicato che voglio più libertà nei miei valori di inserimento, per esempio avere liste separate da virgola all'interno del valore di una voce. Quindi Map.toString() non funzionerà. –

0

immagino qualcosa come questo sarebbe stato più pulito, e offrire una maggiore flessibilità con il formato di output (semplicemente cambiare modello):

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

So di dover rimuovere l'ultimo comma è brutto, ma penso è più pulito di alternative come quella in this solution o manualmente utilizzando un iteratore.

4

guardare il codice per HashMap#toString() e AbstractMap#toString() nelle fonti 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(", "); 
     } 
    } 
} 

Quindi, se i ragazzi di OpenJDK non ha trovato un modo più elegante per fare questo, non c'è nessuno :-)

2
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); 
} 
0

Come soluzione rapida e sporca che sfrutta l'infrastruttura esistente, è possibile avvolgere il uglyPrintedMap in un java.util.HashMap, quindi utilizzare 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 
56

Dai un'occhiata alla biblioteca Guava:

Joiner.MapJoiner mapJoiner = Joiner.on(",").withKeyValueSeparator("="); 
System.out.println(mapJoiner.join(map)); 
221
Arrays.toString(map.entrySet().toArray()) 
+5

Wow .... soluzione incredibilmente semplice e funzionante ... Grazie –

+6

Non così buono se si ha 'Map >', quindi si otterrà questo tipo di pungiglione: '[ test = {test = [D @ 3995ebd8, 2 = [D @ 26fa5067, 3 = [D @ 1d956d37, 4 = [D @ 2cead81, 5 = [D @ 14934d2b} ...] ' – zygimantus

+4

funziona come una magia nera! –

24

librerie di Apache per il salvataggio!

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

Tutto ciò che serve Apache biblioteca Commons-collezioni (project link)

utenti Maven possono aggiungere la libreria utilizzando questa dipendenza:

<dependency> 
    <groupId>commons-collections</groupId> 
    <artifactId>commons-collections</artifactId> 
    <version>3.2.1</version> 
</dependency> 
+0

Questo non gestisce gli array come valori della mappa (ad esempio 'Map '). Vengono stampati solo i nomi di classe e hash invece dei valori effettivi. –

8

Quando ho org.json.JSONObject nel classpath, che faccio:

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

(questo bellissimo elenco di rientri, imposta un e mappe che possono essere annidate)

6

Semplice e facile. Benvenuti nel mondo JSON. Utilizzando Google's Gson:

new Gson().toJson(map) 

Esempio di mappa con 3 chiavi:

{"array":[null,"Some string"],"just string":"Yo","number":999} 
1

utilizzando 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); 
+0

Se stai per aprire una domanda, almeno rispondila correttamente! Ti mancano le virgolette attorno al valore e dovrebbe essere unito usando ',' – AjahnCharles

2

preferisco per convertire la carta in una stringa JSON è:

  • uno standard
  • leggibile
  • supportato in editor come Sublime, codice VS, con la sintassi evidenziazione, la formattazione e la sezione nascondere/mostrare
  • supporta JPath modo editor possono riferire esattamente quale parte dell'oggetto già raggiunta in
  • supporta tipi complessi annidati all'interno dell'oggetto

    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 ""; 
    } 
    
Problemi correlati