Как сгруппировать вложенные карты - PullRequest
0 голосов
/ 06 января 2019

Моя текущая попытка:

Map<Integer, Map<String, Integer>> collect = shopping.entrySet()
            .stream()
            .collect(Collectors.toMap/*groupingBy? */(e -> e.getKey().getAge(),
                    e -> e.getValue().entrySet().stream().collect(Collectors.groupingBy(b -> b.getKey().getCategory(), Collectors.summingInt(Map.Entry::getValue)))));

shopping в основном карта: Map<Client, Map<Product,Integer>>,

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

Как я могу заставить этот код работать также для нескольких ключей?

Полагаю, его нужно как-то изменить, чтобы использовать collect collect(Collectors.groupingBy) ->

в полученной карте Map<Integer, Map<String, Integer>>:

  • Внешний ключ (Integer) представляет возраст клиента.
  • Внутренний ключ (строка) - представляет категорию продукта
  • Значение внутренних карт (целое число) - представляет количество продуктов которые принадлежат к определенной категории.

Моя попытка с использованием группировкиBy:

Map<Integer, Map<String, Integer>> collect = shopping.entrySet()
            .stream()
            .collect(Collectors.groupingBy(/*...*/))

Просто я хочу преобразовать этот код в один, используя потоки:

Map<Integer, Map<String, Integer>> counts = new HashMap<>();

 for (Map.Entry<Client, Map<Product, Integer>> iData : shopping.entrySet()) {
      int age = iData.getKey().getAge();
      for (Map.Entry<Product, Integer> iEntry : iData.getValue().entrySet()) {
        String productCategory = iEntry.getKey().getCategory();
        counts.computeIfAbsent(age, (agekey) -> new HashMap<>()).compute(productCategory, (productkey, value) -> value == null ? 1 : value + 1);
      }
    }

Ответы [ 2 ]

0 голосов
/ 06 января 2019

Это было бы более уместно через groupingBy коллектор вместо toMap.

 Map<Integer, Map<String, Integer>> result = shopping.entrySet()
            .stream()
            .collect(groupingBy(e -> e.getKey().getAge(),
                        flatMapping(e -> e.getValue().keySet().stream(),
                            groupingBy(Product::getCategory,
                                    summingInt(e -> 1)))));

обратите внимание, это использует flatMapping, который доступен только в стандартной библиотеке с jdk9.

0 голосов
/ 06 января 2019

Неконтурный (forEach) способ преобразования вашего цикла for может быть следующим:

Map<Integer, Map<String, Integer>> counts = new HashMap<>();
shopping.forEach((key, value1) -> value1.keySet().forEach(product ->
        counts.computeIfAbsent(key.getAge(),
                (ageKey) -> new HashMap<>())
                .merge(product.getCategory(), 1, Integer::sum)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...