Android流平均来自地图

时间:2017-08-09 08:32:27

标签: android dictionary lambda java-stream average

我有一个对象列表

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

1 个答案:

答案 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");