如何对嵌套地图进行分组

时间:2019-01-06 14:24:22

标签: java java-stream

我当前的尝试:

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>>中:

  • 外键(整数)代表客户年龄。
  • 内键(String)-代表产品类别
  • 内部映射值(整数)-表示产品数量 属于特定类别。

我尝试使用分组方式

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 :(得分:2)

一种非流式(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)));

答案 1 :(得分:1)

通过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以后的标准库中可用。