Java собрать вложенный поток карт, возвращающий предметы верхнего уровня - PullRequest
2 голосов
/ 16 июня 2020

У меня следующая модель:

class Item {
    String name;
    ...
    List<SubItem> subItems;
}

class SubItem {
    String name;
    ...
    List<String> ids;
}

Для каждого id в subItem.ids я хотел бы извлечь некоторые параметры верхнего уровня. Для этого я определил собственный кортеж:

class AdditionalParams {
    private final String itemName;
    private final String subItemName;
    ...
}

Цель - вернуть Map<String, AdditionalParams> (ключ: id в subItem.ids, значение: AdditionalParams для этого идентификатора).

I Предположим, что идентификаторы уникальны, поэтому при добавлении элементов на карту не будет конфликтов.

Мое решение

Я пытался использовать flatMap с Collectors.toMap:

List<Item> allItems = ...
Map<String, AdditionalParams> result = allItems
    .stream()
    .flatMap(i -> i.getSubItems()
                   .stream()
                   .map(si -> si.getIds()
                                .stream()
                                .collect(
                                    Collectors.toMap(
                                        Function.identity(),
                                        id -> new AdditionalParams(i.getName(), si.getName())
                                    )
                                )
                   )
    )  // Stream< Map<String, AdditionalParams> >
    .collect(
        Collectors.toMap(m -> m.getKey(), m -> m.getValue())
    )

Проблема в том, что последняя строка (.collect(Collectors.toMap(...) не работает (или я делаю не так). Я попытался последовать этому ответу Преобразовать список карт в отдельную карту через потоки , но также не смог заставить его работать.

Что я делаю не так со своим подходом? Как мне получить результат типа Map<String, AdditionalParams>?

А как еще сделать его чище / быстрее / лучше? (я знаю, что мое решение далеко от совершенства) .

1 Ответ

1 голос
/ 16 июня 2020

Чтобы исправить это, вы могли бы вместо этого сопоставить промежуточное состояние с записями карты, а затем собрать их. Это будет go как -

Map<String, AdditionalParams> result = allItems
        .stream()
        .flatMap(item -> item.getSubItems().stream()
                .flatMap(subItem -> subItem.getIds()
                        .stream()
                        .map(id -> new AbstractMap.SimpleEntry<>(
                                id, new AdditionalParams(item.getName(),
                                subItem.getName())))))
        .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey,
                AbstractMap.SimpleEntry::getValue));
...