Java 8流聚合了一个映射

时间:2015-02-19 04:37:59

标签: java lambda java-8 java-stream

我试图做一些看似直截了当的事,但到目前为止没有运气。我有一个 Map 列表,它们来自一堆CompletableFutures并行,然后必须加入结果。由于映射中的键是唯一的,因此需要合并值并生成与SomeType的组合列表关联的唯一键的新映射。例如:

地图1: key1:Sometype1 key2:Sometype2

地图2 key1:Sometype3 key2:Sometype4

期望的最终结果: MAP3: key1:Sometype,Sometype3 key2:Sometype2,Sometype4

我尝试使用groupBy和其他方法,但似乎大多数人都假设使用List而不是Map来开始,所以我无法找到一种直接的方法来实现它。

到目前为止,我有类似的内容:

 Map<String, List<Sometype>> volPercent = waitGroup.stream()
            .map(CompletableFuture::join)
            .flatMap((e) -> e.entrySet().stream())
            .collect(Collectors.groupingBy());

我不确定的部分是否需要分组。我尝试了Map.Entry :: getKey,但它没有编译:

Error:(69, 25) java: incompatible types: inference variable T has incompatible bounds
equality constraints: com.Sometype
lower bounds: java.util.Map.Entry<java.lang.String,com.Sometype>

2 个答案:

答案 0 :(得分:6)

我假设您从一组地图开始:

Stream<Map<String, Sometype>> input = ... ;

你在平面图和收集方面做得很好。但是,你试过的代码,

    input.flatMap(map -> map.entrySet().stream())
         .collect(Collectors.groupingBy(Map.Entry::getKey));

为您提供一个地图,其键为String,其值为地图条目的列表,特别是List<Map.Entry<String,Sometype>>,而不是您想要的List<Sometype>。你要做的是使用&#34;下游&#34;收藏家的功能在您按键分组后。您希望获取每个Map.Entry并将其提取(映射)到其值Sometype。这是通过mapping收集器完成的。

现在,每个密钥可能有多个Sometype个实例,因此您需要将它们收集到一个列表中。这是使用另一个下游收集器完成的,它将它们收集到一个列表中。这是使用熟悉的toList()收集器完成的。

最终代码如下:

Map<String, List<Sometype>> result =
    input.flatMap(map -> map.entrySet().stream())
         .collect(groupingBy(Map.Entry::getKey,
                             mapping(Map.Entry::getValue,
                                     toList())));

答案 1 :(得分:2)

问题在于你最初的尝试(据我所知)

Collectors.groupingBy(Map.Entry::getKey)

收集到Map<K, List<Map.Entry<K, V>>>

flatMap之后,您有一个Stream<Map.Entry<K, V>>,其元素groupingBy映射到K

但您需要Map<K, List<V>>,因此您需要使用groupingBy that takes a downstream collector,而不仅仅是分类器,因此您还可以将Map.Entry<K, V>映射到V

这样的东西
Collectors.groupingBy(
    Map.Entry::getKey,
    Collectors.mapping(
        Map.Entry::getValue,
        Collectors.toList()
    )
)