Java 8流 - 合并地图并计算“值”的平均值

时间:2017-11-30 09:27:08

标签: java lambda java-8 java-stream

假设我有List个类,每个类都有Map

public class Test {
    public Map<Long, Integer> map;
}

Long中的Map个密钥是时间戳,Integer值是分数。

我正在尝试创建一个Stream,可以组合所有对象的地图,并输出Map和唯一的时间戳(Long s)和平均分数。

我有这段代码,但是它给了我所有分数的总和而不是平均值Integer类没有平均值法)。

Test test1 = new Test();
    test1.map = new HashMap() {{
        put(1000L, 1);
        put(2000L, 2);
        put(3000L, 3);
    }};

    Test test2 = new Test();
    test2.map = new HashMap() {{
        put(1000L, 10);
        put(2000L, 20);
        put(3000L, 30);
    }};

    List<Test> tests = new ArrayList() {{
        add(test1);
        add(test2);
    }};

    Map<Long, Integer> merged = tests.stream()
            .map(test -> test.map)
            .map(Map::entrySet)
            .flatMap(Collection::stream)
            .collect(
                    Collectors.toMap(
                            Map.Entry::getKey,
                            Map.Entry::getValue,
                            Integer::sum

                    )
            );
    System.out.println(merged);

我认为这可能不是一个简单的问题,所以要在一个Stream中解决,所以输出Map具有唯一的时间戳和所有的List分数也没问题。然后我可以自己计算平均值。

Map<Long, List<Integer>> 

有可能吗?

1 个答案:

答案 0 :(得分:6)

而不是Collectors.toMap使用Collectors.groupingBy

Map<Long, Double> merged = tests.stream()
        .map(test -> test.map)
        .map(Map::entrySet)
        .flatMap(Collection::stream)
        .collect(
                Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.averagingInt(Map.Entry::getValue)
                )
        );

哦,即使你可能不再需要它,你也可以轻松地在问题的最后部分得到你问过的Map<Long, List<Integer>>

Map<Long, List<Integer>> merged = tests.stream()
    .map(test -> test.map)
    .map(Map::entrySet)
    .flatMap(Collection::stream)
    .collect(
            Collectors.groupingBy(
                    Map.Entry::getKey,
                    Collectors.mapping(Map.Entry::getValue, Collectors.toList())
            )
    );