2012-04-12 5 views
94

Ich bin auf der Suche nach einer schönen Möglichkeit, einen Map hübsch zu drucken.Pretty-print eine Karte in Java

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

ich mehr Freiheit in meiner MapEintrag Werte wollen und bin auf der Suche nach etwas mehr wie folgt aus:

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(); 
: key1="value1", key2="value2", key3="value3"

ich dieses kleine Stück Code geschrieben

Aber ich bin mir sicher, dass es einen eleganteren und prägnanteren Weg gibt, dies zu tun.

+1

möglich Duplikat [Karte zu String in Java] (http://stackoverflow.com/questions/2828252/map-to-string-in-java), weil das hier angeforderte Format und das von 'System.out.println' zu nahe sind. Und wenn Sie etwas Brauchbares wollen, dann läuft das alles darauf hinaus, "wie man über eine Map in Java iteriert", was sicherlich viele andere Antworten hat. –

Antwort

50

Oder setzen Sie Ihre Logik in eine saubere kleine Klasse.

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

    } 
} 

Verbrauch:

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

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

Hinweis: Sie können auch diese Logik in eine Hilfsmethode setzen.

1

Sie sollten in der Lage sein zu tun, was Sie wollen, indem Sie:

System.out.println(map) zum Beispiel

Solange alle Ihre Objekte in der Karte die toString Methode overiden haben Sie würden sehen:
{key1=value1, key2=value2} in a sinnvolle Art und Weise

Wenn dies für Ihren Code ist, dann ist toString eine gute Angewohnheit, und ich schlage vor, dass Sie stattdessen dafür gehen.

Für Ihr Beispiel, wo Ihre Objekte sind String s sollten Sie in Ordnung, ohne etwas anderes.
I.e. System.out.println(map) würde genau das drucken, was Sie brauchen, ohne zusätzlichen Code

+1

seine Schlüssel und Werte sind Zeichenfolgen; Ich denke, er hat die toString Methode behandelt. – Tom

+0

Sie haben Recht, aber vielleicht hat er ein triviales Beispiel kopiert, um seinen Standpunkt zu verdeutlichen. Aber ich aktualisiere die Antwort – Cratylus

+0

Ja, ich hätte angeben sollen, dass meine Karte Map ist. Aber ich habe auch angegeben, dass ich mehr Freiheit in meinen Eingabewerten haben möchte, zum Beispiel mit kommagetrennten Listen innerhalb eines Eintrags. Also Map.toString() wird nicht tun. –

0

Ich denke, so etwas wie dieser sauberer sein würde, und bieten Ihnen mehr Flexibilität mit dem Ausgabeformat (einfach Vorlage ändern):

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

Ich weiß, die das letzte Komma ist hässlich zu entfernen, aber ich denke, es ist sauberer als Alternativen wie die in this solution oder manuell mit einem Iterator.

4

Blick auf den Code für HashMap#toString() und AbstractMap#toString() in den OpenJDK Quellen:

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(", "); 
     } 
    } 
} 

Also, wenn die Jungs von OpenJDK haben leider eine elegantere Weg, dies zu tun, gibt es keine :-)

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

Als eine schnelle und schmutzige Lösung, die die vorhandene Infrastruktur nutzt, können Sie Ihre uglyPrintedMap in eine java.util.HashMap verpacken und dann toString() verwenden.

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

Werfen Sie einen Blick auf die Guava Bibliothek:

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

Wow .... erstaunlich einfach und funktionierende Lösung ... Danke –

+6

Nicht so gut, wenn Sie haben > ', dann erhalten Sie diese Art von Stachel:' [ test = {test = [D @ 3995ebd8, 2 = [D @ 26fa5067, 3 = [D @ 1d956d37, 4 = [D @ 2cead81, 5 = [D @ 14934d2b] ...] ' – zygimantus

+4

funktionieren wie eine schwarze Magie! –

24

Apache-Bibliotheken zur Rettung!

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

Alles was Sie brauchen Apache commons-Sammlungen Bibliothek (project link)

Maven Benutzer können die Bibliothek mit dieser Abhängigkeit hinzu:

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

Dies behandelt nicht Arrays als Map-Werte (zB. Map '). Nur der Klassenname und der Hash werden anstelle von tatsächlichen Werten gedruckt. –

8

Als ich org.json.JSONObject im Classpath, ich tun:

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

(diese schönen Einzüge listet, legt ein nd Karten, die verschachtelt sein können)

6

Einfach und leicht. Willkommen in der JSON-Welt. Google's Gson Verwendung:

new Gson().toJson(map) 

Beispiel Karte mit 3 Tasten:

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

mit 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

Wenn Sie eine Frage verneinen wollen, antworten Sie zumindest richtig! Sie fehlen die Anführungszeichen um den Wert und es sollte mit ',' verbunden werden – AjahnCharles

2

Ich ziehe die Karte in eine JSON-Zeichenfolge zu konvertieren ist:

  • ein Standard
  • Menschen lesbare
  • in Editoren wie Sublime unterstützt, VS-Code, mit Syntax Hervorhebung, Formatierung und Abschnitt hide/show
  • JPath unterstützt so Redakteure berichten genau, welcher Teil des Objekts Sie
  • Navigation gestartet haben,
  • unterstützt verschachtelte komplexe Typen innerhalb des Objekts

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