Как пробежаться по вложенным Map?

415
10 июня 2017, 13:46

Есть map вида Map<BigInteger, Map<BigInteger, Object>> В реальности иерархия гораздо сложнее. Как пробежаться по всем маппам и везде, где встречено нужное значение ключа - произвести замену значения?

Answer 1

Для сложной иерархии с непонятной степенью вложенности хорошо подойдет рекурсия, метод в итоге возвращает сколько всего замен было сделано:

@SuppressWarnings("unchecked")
private static int findReplaceValueByKey(int key, String newValue, Map<Integer, Object> map) {
    int count = 0;
    for (Object o : map.values()) {
        if (o instanceof Map) {
            count = findReplaceValueByKey(key, newValue, (Map<Integer, Object>) o);
        }
    }
    if (map.replace(key, newValue) != null) {
        count++;
    }
    return count;
}
Answer 2

Если нужно пробежаться по всем мапам самого глубокого уровня вложенности, то можно попробовать вложенные циклы foreach или функционалку:

// Map<BigInteger, Map<BigInteger, Map<BigInteger, Map<BigInteger, Object>>>> test;
// BigInteger compare_key;
// foreach
for ( Map<BigInteger, Map<BigInteger, Map<BigInteger, Object>>> v1 : test.values() )
    for ( Map<BigInteger, Map<BigInteger, Object>> v2 : v1.values() )
        for ( Map<BigInteger, Object> v3 : v2.values() )
            v3.computeIfPresent(compare_key, (key,value) -> null /* вместо "null" здесь должен быть расчёт нового значения */);
// то же, но в функционалке
test.values().forEach
(   v1 -> v1.values().forEach
    (   v2 -> v2.values().forEach
        (   v3 -> v3.computeIfPresent(compare_key, (key,value) -> null /* вместо "null" здесь должен быть расчёт нового значения */)
)   )   );

Если же для каждого уровня вложенности имеется свой ключ поиска, то можно попробовать цепочку вложенных вызовов Map::computeIfPresent:

// BigInteger compare_key_1, compare_key_2, compare_key_3;
test.computeIfPresent(compare_key_1, (key_1, value_1) ->
{   value_1.computeIfPresent(compare_key_2, (key_2, value_2) ->
    {   value_2.computeIfPresent(compare_key_3, (key_3, value_3) -> null /* вместо "null" здесь должен быть расчёт нового значения */);
        return value_2;
    });
    return value_1;
});

Если ключи есть не для всех уровней вложенности, то можно и комбинировать:

test.computeIfPresent(compare_key_1, (key_1, value_1) ->
{   value_1.values().forEach // нет ключа сравнения, проверяем все мапы данного уровня вложенности
    (   value_2 ->
        value_2.computeIfPresent(compare_key_3, (key_3, value_3) -> null /* вместо "null" здесь должен быть расчёт нового значения */)
    );
    return value_1;
});

Если я неправильно понял, что требуется, то просьба уточнить вопрос

READ ALSO
Как сделать скриншот dialogfragment

Как сделать скриншот dialogfragment

Публикую в вк результат игрыЕсли публиковать как сообщение , то результат можно редактировать в вк

338
Деконвертация кода из Kotlin в Java

Деконвертация кода из Kotlin в Java

Пользуюсь IntelliJ Idea, решил по фану конвертировать свой код Java-код в Kotlin, дабы поглядеть как выглядят мои алгоритмы на новом языкеНо чуть позже...

182
Как работает compare

Как работает compare

Добрый день, ну никак не могу вникнуть, по какому принципу работает compare, уже где только не читал

298