Java 8流对Map进行聚合

9

我一直在尝试做一些看似简单的事情,但到目前为止都没有成功。我有一个Map列表,它们来自一堆并行的CompletableFutures,然后需要将结果合并。由于映射中的键是唯一的,因此我需要合并值并生成一个新的与组合后的SomeType列表相关联的唯一键的映射。例如:

Map1: key1:Sometype1 key2:Sometype2

Map2: key1:Sometype3 key2:Sometype4

所需的最终结果: Map3: key1:Sometype1,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>

3
请构建一个小的可运行示例来说明您的问题,仅凭一行代码很难解决。 - Keppil
1
上游的CompletableFuture有点分散注意力。未来的问题最好从更明确的输入开始。但我想我能够解决它。 - Stuart Marks
2个回答

14

我假设你开始使用一个地图流:

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

你在使用flatmapping和collecting方面做的很好。然而,你尝试的代码是:

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

给你一个地图,它的键是 String,值是一组地图 条目,具体来说是 List<Map.Entry<String,Sometype>>,而不是你想要的 List<Sometype>。你需要做的是在按键分组后使用收集器的 "downstream" 特性。你想要取出每个 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())));

4
问题在于您的首次尝试(据我所知)存在问题。
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,而不仅仅是分类器,因此您还可以将Map.Entry<K,V>映射到V
类似于:
Collectors.groupingBy(
    Map.Entry::getKey,
    Collectors.mapping(
        Map.Entry::getValue,
        Collectors.toList()
    )
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接