Java 8: Как получить значение из списка, содержащегося в качестве значения карты? - PullRequest
7 голосов
/ 02 апреля 2019

У меня следующая ситуация: у меня есть LinkedHashMap <>, где тип ключа - String, а типы значений различаются: double, String, LinkedHashMap и т. Д. Я пытаюсь извлечь значение из ключа одного изЗначения LinkedHashMaps, которые являются значением основной карты.Например, я хотел бы получить результат 1 из следующего кода (очевидно, это беспорядок, так как он даже не компилируется):

Map<String, Object> input = new HashMap<>();     
input.put("a", "1234");
input.put("b", "2345");
input.put("c", "3456");
input.put("d", new HashMap<String, String>());

HashMap<String, Object> input2 = (HashMap<String, Object>)(input.get("d"));
input2.put("d1", 1);
input2.put("d2", 2);

Optional<Integer> result = input.entrySet().stream()
            .filter(e -> e.getKey().equals("d"))
            .map(Map.Entry::getValue)
            .filter(e -> e.getKey().equals("d1"))
            .findFirst();

Где я ошибаюсь, и, конечно же,Каков наилучший способ получить результат?

Спасибо.

Ответы [ 2 ]

5 голосов
/ 02 апреля 2019

Как только вы используете Map с различными типами значений (и даже ключами) (и еще хуже, вложенные карты).Тогда я предлагаю сделать шаг назад и попытаться проанализировать, что вы сделали.Кажется, с class вы намного лучше, чем с Map.Пример с вашими ключами:

class YourClass {
    String a;
    String b;
    String c;
    YourOtherClass d;
}

class YourOtherClass {
    Integer d1;
    Integer d2;
}

Я упустил геттеры, сеттеры и конструкторы для простоты.

Затем вы можете создавать экземпляры этих объектов, например так:

YourOtherClass yoc = new YourOtherClass(1, 2);
YourClass yc = new YourClass("1234", "2345", "3456", yoc);

А затем вызвать определенный метод получения, чтобы получить значение с типами безопасности:

String a = yc.getA(); // works
Integer i = yc.getA(); // doesn't work

Или установить новое значение через установщик:

yoc.setD1(4); // works
yoc.setD1("4"); // doesn't work
2 голосов
/ 02 апреля 2019

Ты слишком усложняешь вещи, Имо. Вы могли бы сделать это очень простым способом. Один лайнер не всегда идеальное решение.

У меня нет возможности его скомпилировать, но все должно быть в порядке.

public Optional<Integer> getInnerValue(Map<String, Object> map, String outerKey, String innerKey) {
    Object o = map.get(outerKey);
    if (!(o instanceof Map)) {
        return Optional.empty();
    }
    return Optional.ofNullable(((Map)o).get(innerKey));
}

Использование однострочника

public Optional<Integer> getInnerValue(Map<String, Object> map, String outerKey, String innerKey) {
    return Optional.ofNullable(map.get(outerKey))
                   .filter(Map.class::isInstance)
                   .map(Map.class::cast)
                   .map(m -> m.get(innerKey))
                   .findFirst();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...