我有一个对象列表
class Result {
private String name;
private Map<String, Double> map;
// getters, constructor etc
}
我想按名称对其进行分组,并在每个键的地图中为平均值设置双倍值。列表中的每个对象都具有相同键的映射。
我开始按名称分组
Map <String, List<Result>> grouppedByName = Stream.of(results)
.collect(Collectors.groupingBy(Result::getName));
我不知道下一个常规循环的区别。
示例数据:
INPUT:
name = "Name 1"
map:
KEY1, 10
KEY2, 1
name = "Name 1"
map:
KEY1, 20
KEY2, 7
name = "Name 2"
map:
KEY1, 2
KEY2, 3
--------------
OUTPUT:
name = "Name 1"
map:
KEY1, 15 (10+20)/2 = 15
KEY2, 4 (1+7)/2 = 4
name = "Name 2"
map:
KEY1, 2
KEY2, 3
答案 0 :(得分:1)
groupingBy
方法将生成Map<String, List<Result>>
。我们需要一种方法将此地图的List<Result>
值转换为更有用的值:
Map<String, Double> mapMerger(final List<Result> results) {
return results.stream()
.map(Result::getMap)
.map(Map::entrySet)
.flatMap(Set::stream)
.collect(groupingBy(Entry::getKey, averagingDouble(Entry::getValue)));
}
这将从所有结果中的所有地图中提取Entry<String, Double>
类型的所有条目。它会将这些条目聚合到每个键的映射中,并映射到该键的所有值的平均值。
我们可以通过从原始地图创建一个流来应用这种新方法(问题中为grouppedByName
):
Map<String, Map<String, Double>> averagedByName = results.stream()
.collect(groupingBy(Result::getName))
.entrySet().stream()
.collect(toMap(Entry::getKey, e -> mapMerger(e.getValue())));
如果你这样做,你应该得到15
:
double avg = averagedByName.get("Name 1").get("KEY1");