Java'da Harita Yazdırması


136

Güzel bir baskı için güzel bir yol arıyorum Map.

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

Harita giriş değerlerimde daha fazla özgürlük istiyorum ve bunun gibi bir şey arıyorum: key1="value1", key2="value2", key3="value3"

Bu küçük kod parçasını yazdım:

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

Ama eminim ki bunu yapmanın daha zarif ve özlü bir yolu var.


1
Java'da Dize Eşlemesi'nin olası kopyası, burada istenen biçim ve System.out.printlnçok yakın olduğundan. Ve özel bir şey istiyorsanız, bu kesinlikle başka bir cevabı olan "Java'da bir harita üzerinde nasıl yinelenir?"
Ciro Santilli 法轮功 10: 病 六四 事件 法轮功

Yanıtlar:


63

Veya mantığınızı düzenli küçük bir sınıfa koyun.

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

    }
}

Kullanımı:

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

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

Not: Bu mantığı bir yardımcı program yöntemine de koyabilirsiniz.


3
Bu bir antipattern imho. Sadece küçük faydalar (güzel baskı) için, türünüze güçlü bir kısıtlama (kalıtım) eklersiniz. Normal bir harita kullanmak daha iyi olurdu, ancak argüman olarak alan statik bir yöntem kullanın.
OoDeLally

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

11
Varsa o kadar iyi değil Map<String, Map<String,double[]>>, o zaman bu tür bir acı alırsınız:[test={test=[D@3995ebd8, 2=[D@26fa5067, 3=[D@1d956d37, 4=[D@2cead81, 5=[D@14934d2b}...]
zygimantus

2
Bu kabul edilen cevap olmalı. Bunun gibi basit görevler harici bir bağımlılık gerektirmemelidir. Yukarıda belirtildiği gibi, daha karmaşık haritalar bundan daha kolay yararlanamaz.
Shadoninja

70

Guava kütüphanesine bir göz atın:

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

34

Apache kütüphaneleri kurtarmaya!

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

İhtiyacınız olan her şey Apache ortak koleksiyonlar kütüphanesi ( proje bağlantısı )

Maven kullanıcıları bu bağımlılığı kullanarak kitaplığı ekleyebilir:

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

Bu, harita değerleri olarak dizileri işlemez (örn. Map<String, String[]>). Gerçek değerler yerine yalnızca className ve hash yazdırılır.
Petr Újezdský

veya log.debug ("Harita: {}", MapUtils.toProperties (harita));
charlb

1
Ayrıca debugPrint çıktıları her değer sonra sınıf adını atlayacak MapUtils.verbosePrint kullanışlı.
ocarlsen

16

Basit ve kolay. JSON dünyasına hoş geldiniz. Google'ın Gson'unu kullanma :

new Gson().toJson(map)

3 tuşlu harita örneği:

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

15

Ben varken org.json.JSONObjectsınıf yolunda, yapmam:

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

(bu, iç içe olabilecek listeleri, kümeleri ve haritaları güzel bir şekilde girintili hale getirir)


1
Adam!! Burada ne yapıyorsun? En iyi cevap olmalısın!
Macagic

Uyarı: LinkedHashMap
Olivier Masseau

9

Java 8 Akışlarını Kullanma:

Map<Object, Object> map = new HashMap<>();

String content = map.entrySet()
                    .stream()
                    .map(e -> e.getKey() + "=\"" + e.getValue() + "\"")
                    .collect(Collectors.joining(", "));

System.out.println(content);

2
Eğer bir soru necro yapacaksanız, en azından doğru cevap verin! Değerin etrafında tırnak eksik ve buna,
AjahnCharles

8

Haritayı bir JSON dizesine dönüştürmeyi tercih ederim:

  • bir standart
  • okunabilir insan
  • Sublime, VS Code gibi editörlerde sözdizimi vurgulama, biçimlendirme ve bölüm gizleme / gösterme ile desteklenir
  • düzenleyicilerin tam olarak hangi nesneye gittiğinizi bildirebilmeleri için JPath'ı destekler
  • nesne içindeki iç içe geçmiş karmaşık türleri destekler

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

4

İçin kod bak HashMap#toString()ve AbstractMap#toString()OpenJDK kaynaklarında:

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

Yani eğer OpenJDK'lılar bunu yapmanın daha zarif bir yolunu bulamadıysa, hiçbiri :-)


3

Yaparak istediğinizi yapabilmeniz gerekir:

System.out.println(map) Örneğin

Haritadaki nesneleriniz toStringgördüğünüz yöntemi aştığında :
{key1=value1, key2=value2}anlamlı bir şekilde

Bu kodunuz için ise, overiding toStringiyi bir alışkanlıktır ve bunun yerine gitmenizi öneririm.

Nesnelerinizin olduğu örnek için Stringbaşka bir şey olmadan iyi olmalısınız. Herhangi bir ekstra kod olmadan tam olarak ihtiyacınız olanı
basarsınızSystem.out.println(map)


1
anahtarları ve değerleri dize; Bence o toString yöntemi tbh kaplı.
Tom

Haklısınız, ama belki de onun point.But ben güncelleme cevabı yapmak için önemsiz bir örnek kopyalanmış
Kratilus'unda

Evet, haritamın Map <String, String> olduğunu belirtmeliydim. Ama aynı zamanda girdi değerlerimde daha fazla özgürlük istediğimi, örneğin bir girdinin değeri içinde virgülle ayrılmış listelere sahip olduğumu belirttim. Map.toString () işe yaramaz.
space_monkey

Arayüz ile java.util.Mapilgili herhangi bir sözleşme yoktur toString(), bu yüzden -> -> -> Mapneyin neden olacağı gerçek uygulamaya bağlıdır . Sık kullanılan , güzel bir dize temsili sağlar . ... Diğer uygulamalara geri dönülebilir , bu da çok bilgilendirici değildir . System.out.println(map)PrintStream.println(map)String.valueOf(map)map.toString()java.util.AbstractMaptoString()MapObject.toString()com.example.MyMap@4e8c0de
Abdull

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

Bunun gibi bir şey daha temiz olacağını tahmin ve çıktı biçimi (sadece şablon değiştirmek) ile daha fazla esneklik sağlar:

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

Son virgül kaldırmak zorunda çirkin biliyorum, ama bence bu çözümde olduğu gibi alternatifler ya da bir yineleyici kullanarak daha temiz .


0

Hızlı ve kirli çözüm kaldıraç altyapısını mevcut, durumu sarabilirsiniz uglyPrintedMapbir içine java.util.HashMap, daha sonra kullanmak 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

Soruyu tam olarak cevaplamıyor, ancak Lombodok @ToString notundan bahsetmeye değer . Birlikte açıklama ise sınıflar, daha sonra yapıyor anlamlı bir şey dönecektir.@ToStringkey / valueSystem.out.println(map)

Aynı zamanda, örneğin, haritalar-of-the haritalarla çok iyi çalışır: Map<MyKeyClass, Map<String, MyValueClass>>olarak basılacaktır

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


0

String result = objectMapper.writeValueAsString(map) - bu kadar basit!

Sonuç:

{"2019-07-04T03:00":1,"2019-07-04T04:00":1,"2019-07-04T01:00":1,"2019-07-04T02:00":1,"2019-07-04T13:00":1,"2019-07-04T06:00":1 ...}

PS, Jackson JSON 'ı sınıf yolunuza ekleyin


0

Java 8'den beri Lambda ile yapmanın kolay yolu var:

yourMap.keySet().forEach(key -> {
    Object obj = yourMap.get(key);
    System.out.println( obj);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.