После выравнивания многоуровневой карты Java 8 мой ожидаемый результат будет пустым - PullRequest
1 голос
/ 09 марта 2020

У меня есть многоуровневая карта ниже:

Map<String, List<Map<String, Map<String, Map<String, Map<String, String>>>>>> input =
                ImmutableMap.of("A",
                        ImmutableList.of(ImmutableMap.of("2",
                                ImmutableMap.of("3",
                                        ImmutableMap.of("4",
                                                ImmutableMap.of("5", "a"))))));

Короче говоря, это будет похоже на

 {
 "A":[{"2":{"3":{"4":{"5":"a"}}}}],
 "B":[{"2":{"3":{"4":{"5":"b"}}}}]
 }

Мое требование - построить карту вида

{
 "A":"a", 
 "B":"b"
}

Я попробовал приведенный ниже код, но по какой-то причине myMap всегда пуст, даже если я его заполняю. Что мне не хватает?

Map<String, String> myMap = new HashMap<>();
input.entrySet()
                .stream()
                .map(l -> l.getValue().stream().map(m -> m.get(m.keySet().toArray()[0]))
                                .map(n -> n.get(n.keySet().toArray()[0]))
                                .map(o -> o.get(o.keySet().toArray()[0]))
                                .map(p -> myMap.put(l.getKey(), p.get(p.keySet().toArray()[0])))).collect(Collectors.toList());
System.out.println(myMap);

1 Ответ

1 голос
/ 09 марта 2020

Вот что я получаю, когда добавляю два peek вызова в ваш конвейер:

input.entrySet().stream()
  .peek(System.out::println)     //<- this
  .map(l -> ...)
  .peek(System.out::println)     //<- and this
  .collect(Collectors.toList());

output:

A=[{2={3={4={5=a}}}}]
java.util.stream.ReferencePipeline$3@d041cf

Если вы заметили проблему, вы собираете потоки и эти потоки не выполняются через вызов терминальной операции ... Когда я пытаюсь добавить что-то вроде .count() во внутренний поток, вы получите ожидаемый результат:

...
.map(l -> l.getValue().stream().map(m -> m.get(m.keySet().toArray()[0]))
        .map(n -> n.get(n.keySet().toArray()[0]))
        .map(o -> o.get(o.keySet().toArray()[0]))
        .map(p -> myMap.put(l.getKey(), p.get(p.keySet().toArray()[0])))
        .count()) //just an example
...

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

В довольно отчаянной попытке упростить этот код, поскольку поток, кажется, затрудняет его чтение, я подумал, что вы это может быть интересным, что предполагает, что ни одна коллекция не является пустой в дереве, но, по крайней мере, содержит запись как один объект, а не коллекцию записей (но я уверен, что ни один код не будет выглядеть чистым для этой глубокой карты карт ).

String key = input.keySet().iterator().next();
String value = input.entrySet().iterator().next()
                .getValue().get(0)
                .values().iterator().next()
                .values().iterator().next()
                .values().iterator().next()
                .values().iterator().next();
myMap.put(key, value);
...