Расширение карты на карту на основе ключа - PullRequest
1 голос
/ 20 февраля 2020

Если у меня есть карта типа:

Map.of("key1", "value1",
       "key2.subkey1", "subvalue1",
       "key2.subkey2", "subvalue2",
       "key2.subkey3.subsubkey", "subsubvalue");

Тогда я хотел бы преобразовать ее в карту (возможно) карт, подобную этой:

Map.of("key1", "value1",
       "key2", Map.of("subkey1", "subvalue1",
                      "subkey2", "subvalue2",
                      "subkey3", Map.of("subsubkey", "subsubvalue)));

Я думаю, что мне нужно разделить клавиши следующим образом:

entry.getKey().split("\\.", 2);

Но я не могу понять, что делать после этого.

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Мне нравится использовать рекурсию в этих случаях (каскадные ключи):

public static Map<String, Object> covert(Map<String, String> map) {
    Map<String, Object> result = new HashMap<>();
    map.forEach((key, value) -> parseAndPut(result, key, value));
    return result;
}

@SuppressWarnings("unchecked")
private static void parseAndPut(Map<String, Object> map, String key, String value) {
    String[] keys = key.split("\\.");
    if (keys.length == 1) {
        map.put(key, value);
    } else if (keys.length > 1) {
        String subKey = keys[0];
        Map<String, Object> valueMap = (Map<String, Object>) map.computeIfAbsent(subKey, s -> new HashMap<>());
        int beginIndex = key.indexOf(subKey) + subKey.length() + 1;
        parseAndPut(valueMap, key.substring(beginIndex), value);
    }
}

Вывод для ваших входных данных:

{key1=value1, key2={subkey1=subvalue1, subkey2=subvalue2, subkey3={subsubkey=subsubvalue}}}
0 голосов
/ 20 февраля 2020

Мне удалось сделать этот метод, который делает то, что я хочу, но он выглядит не очень красиво: (

private Map<String, Object> expandMap(Map<String, String> oldMap) {
    HashMap<String, Object> newMap = new HashMap<>();
    oldMap.forEach((key, value) -> {
        String[] keys = key.split("\\.", 2);
        if (keys.length == 1) {
            newMap.put(keys[0], value);
        } else {
            newMap.merge(keys[0], expandMap(Map.of(keys[1], value)), (obj1, obj2) -> {
                if (obj1 instanceof Map && obj2 instanceof Map) {
                    Map<String, Object> map1 = (Map<String, Object>) obj1;
                    Map<String, Object> map2 = (Map<String, Object>) obj2;
                    return Stream.concat(map1.entrySet().stream(), map2.entrySet().stream()).collect(toMap(Entry::getKey, Entry::getValue));
                }
                return null;
            });
        }
    });
    return newMap;
}

Вы можете поделиться своими мыслями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...