Java8流聚合图
Java 8 stream aggregate a map
我正在尝试做一些看似简单但到目前为止运气不佳的事情。我有一个 Map 的列表,它们来自一堆并行的 CompletableFutures,然后必须加入结果。由于映射中的键是唯一的,因此需要合并值并生成与 SomeType 的组合列表关联的唯一键的新映射。例如:
地图1:
key1 : Sometype1
key2 : Sometype2
地图2
key1 : Sometype3
key2 : Sometype4
期望的最终结果:
地图3:
key1 : 某种类型,某种类型 3
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>
问题是你最初的尝试(据我了解)
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()
)
)
我假设您从一系列地图开始:
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>
如你所愿。您需要做的是在按键分组后使用收集器的 "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())));
我正在尝试做一些看似简单但到目前为止运气不佳的事情。我有一个 Map 的列表,它们来自一堆并行的 CompletableFutures,然后必须加入结果。由于映射中的键是唯一的,因此需要合并值并生成与 SomeType 的组合列表关联的唯一键的新映射。例如:
地图1: key1 : Sometype1 key2 : Sometype2
地图2 key1 : Sometype3 key2 : Sometype4
期望的最终结果: 地图3: key1 : 某种类型,某种类型 3 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>
问题是你最初的尝试(据我了解)
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()
)
)
我假设您从一系列地图开始:
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>
如你所愿。您需要做的是在按键分组后使用收集器的 "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())));