Вопрос по pretty-print, dictionary, java – Pretty-распечатать карту в Java

117

Я ищу хороший способ красиво распечататьMap.

map.toString() дает мне:{key1=value1, key2=value2, key3=value3}

Я хочу больше свободы в значениях записей моей карты и ищу что-то более похожее на это:key1="value1", key2="value2", key3="value3"

Я написал этот маленький кусочек кода:

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

Но я уверен, что есть более элегантный и лаконичный способ сделать это.

возможный дубликатMap to String in Java потому что формат, запрошенный здесь, и форматSystem.out.println слишком близко И если вам нужно что-то нестандартное, это сводится к тому, «как перебирать карту в Java». у которого конечно есть много других ответов. Ciro Santilli 新疆改造中心 六四事件 法轮功

Ваш Ответ

14   ответов
11

Google's Gson:

new Gson().toJson(map)

Пример карты с 3 ключами:

{"array":[null,"Some string"],"just string":"Yo","number":999}
Почему отрицательный голос?
56

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

    }
}

Использование:

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

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

Примечание. Вы также можете поместить эту логику в служебный метод.

2

System.out.println(map) например

Пока ВСЕ ваши объекты на карте имеютtoString метод, который вы увидите:
{key1=value1, key2=value2} осмысленно

Если это для вашего кода, то overidingtoString это хорошая привычка, и я предлагаю вам пойти на это вместо этого.

Для вашего примера, где ваши объектыStringС тобой должно быть все в порядке без всего остального.
То естьSystem.out.println(map) будет печатать именно то, что вам нужно, без дополнительного кода

Вы правы, но, возможно, он скопировал тривиальный пример, чтобы высказать свою точку зрения. Но я обновляю ответ
его ключи и значения являются строками; Я думаю, он получил метод toString.
Да, я должен был указать, что моя карта - это карта & lt; String, String & gt ;. Но я также указал, что я хочу больше свободы в моих значениях записи, например, иметь разделенные запятыми списки в значении записи. Поэтому Map.toString () этого не сделает. space_monkey
Интерфейсjava.util.Map не имеет договора относительноtoString()так что до фактическогоMap реализация чтоSystem.out.println(map) - & GT;PrintStream.println(map) - & GT;String.valueOf(map) - & GT;map.toString() будет вызывать. Бывает, что часто используемыеjava.util.AbstractMap обеспечивает хорошее строковое представление дляtoString(), ... ДругойMap реализации могут отступить кObject.toString()что приводит к не очень информативным[email protected].
5

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

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

System.out.println(content);
Если вы собираетесь ответить на вопрос, по крайней мере, ответьте правильно! Вы пропускаете кавычки вокруг значения, и к нему следует присоединиться, используя,
6

a standard human readable supported in editors like Sublime, VS Code, with syntax highlighting, formatting and section hide/show supports JPath so editors can report exactly which part of the object you have navigated to

supports nested complex types within the object

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

что-то вроде этого будет чище, и даст вам больше гибкости с выходным форматом (просто измените шаблон):

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

Я знаю, что убирать последнюю запятую - это ужасно, но я думаю, что она чище, чем альтернативы, такие какв этом решении или вручную с помощью итератора.

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

@ToString аннотирование, Если вы аннотируете с@ToString key / value классы, затем делатьSystem.out.println(map) вернет что-то значимое.

Он также очень хорошо работает с картами карт, например: Map<MyKeyClass, Map<String, MyValueClass>> будет напечатан как

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

0

использующее существующую инфраструктуру, вы можетеuglyPrintedMap вjava.util.HashMapзатем используйте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
66

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

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

Все, что вам нужно, библиотека Apache commons-collection (ссылка на проект)

Пользователи Maven могут добавить библиотеку, используя эту зависимость:

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>
Это не обрабатывает массивы как значения карты (например,Map<String, String[]>). Только их className и hash печатаются вместо фактических значений.
или log.debug (& quot; Map: {} & quot ;, MapUtils.toProperties (map));
4

HashMap#toString() а такжеAbstractMap#toString() в источниках 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(", ");
        }
    }
}

Так что, если ребята из OpenJDK не нашли более элегантный способ сделать это, то их нет :-)

11

org.json.JSONObject в classpath я делаю:

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

(это красиво оформленные списки, множества и карты, которые могут быть вложенными)

Мужчина!! Что ты здесь делаешь? Вы должны быть лучшим ответом!
Предупреждение: не сохраняет порядок ключей для LinkedHashMap
270
Arrays.toString(map.entrySet().toArray())
работать как черная магия!
Это должен быть принятый ответ. Простые задачи, подобные этой, не должны требовать внешней зависимости. Как упомянуто выше, более сложные карты не получают такой же легкой выгоды от этого.
Вау .... Удивительно простое и рабочее решение ... Спасибо
Не так хорошо, если у вас естьMap<String, Map<String,double[]>>тогда вы получите этот тип укуса:[test={test=[[email protected], 2=[[email protected], 3=[[email protected], 4=[[email protected], 5=[[email protected]}...]

Похожие вопросы