Как мне сгенерировать карту карты списка (карта >) в java с использованием потоков - PullRequest
0 голосов
/ 21 апреля 2020

Дано:

enum Food{
FRUITS, VEGGIES;
}

Map<String, List<String>> basketMap = new HashMap<>();
basketMap .put("bucket1", Arrays.asList("apple", "banana"));
basketMap .put("bucket2", Arrays.asList("orange", "kiwi"));
basketMap .put("bucket3", Arrays.asList("banana", "orange"));

Требуется сгенерировать карту карты списка (populte fruitBaskerMap)

Map<String, Map<Food, List<String>> fruitBasketMap = new HashMap<>();

Окончательный вывод:

fruitBasketMap:
[
bucket1, [Food.FRUITS, {"apple", "banana"}],
bucket2, [Food.FRUITS, {"orange", "kiwi"}],
bucket3, [Food.FRUITS, {"banana", "orange"}]
]

Я пытался ниже (но не удалось)

fruitBasketMap = basketMap.entrySet().stream().collect(
    Collectors.toMap(Map.Entry::getKey,
        Collectors.toMap(Food.FRUITS,
            Collectors.toList(Map.Entry::getValue())
        )
    )
);

Может кто-нибудь дать мне знать, как мне это сделать?

Ответы [ 4 ]

1 голос
/ 21 апреля 2020

Эта реализация, кажется, работает (используя Java 9 Map.of):

Map<String, Map<Food, List<String>>> fruitBasketMap = basketMap.entrySet().stream()
        .map(e -> Map.entry(e.getKey(), Map.of(Food.FRUITS, e.getValue())))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Вывод теста:

{
bucket2={FRUITS=[orange, kiwi]}, 
bucket3={FRUITS=[banana, orange]}, 
bucket1={FRUITS=[apple, banana]}
}
0 голосов
/ 22 апреля 2020

Это будет работать с Java 8

Map<String, Map<Food, List<String>>> collect = basketMap.entrySet().stream().collect(
                Collectors.toMap(basketMapEntry -> basketMapEntry.getKey(),
                        basketMapEntry -> basketMapEntry.getValue().stream()
                                .collect(Collectors.groupingBy(
                                        item -> type.get(item)
                                        )
                                )
                )
        );

Я использую сборщик groupingBy для группировки списка элементов на основе перечисления. Предполагается, что существует карта, чтобы узнать стоимость продуктов питания на основе записи. Что-то вроде:

Map<String, Food> type = new HashMap<>();
        type.put("apple", Food.FRUITS);
        type.put("banana", Food.FRUITS);
        type.put("orange", Food.FRUITS);
        type.put("kiwi", Food.FRUITS);
        type.put("kiwi", Food.FRUITS);
        type.put("potato", Food.VEGGIES);
        type.put("carrot", Food.VEGGIES);
0 голосов
/ 21 апреля 2020

Это должно сделать трюк Java 8+ способом:

fruitBasketMap = 
    basketMap.entrySet()
             .stream()
             .collect(groupingBy(Entry::getKey,
                                 toMap(e -> Food.FRUITS, Entry::getValue)));

Приведенный выше коллектор работает следующим образом:

  1. Группирует элементы по их ключам таким образом, ключи остаются такими же, как и в исходной карте.
  2. Собирает записи в новую карту с помощью
    • key: Food.FRUITS (постоянная для всех записей)
    • значение: исходное значение (список строк)
0 голосов
/ 21 апреля 2020

Вы можете достичь этого Java -8. Попробуйте следующее. Поскольку на внутренней карте всегда будет одна запись, вы можете использовать singletonMap

Map<String, Map<Food, List<String>>> result = basketMap.entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> Collections.singletonMap(Food.FRUITS, entry.getValue())));
...