Java 8流 - 合并映射并计算“值”的平均值

5

假设我有一个包含每个类都有一个MapList

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

Map中的Long键是时间戳,Integer值是分数。

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

我有这段代码,但它给我所有分数的总和而不是平均值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也是可以的。然后我可以自己计算平均值。

Map<Long, List<Integer>> 

可以吗?
1个回答

8

使用 Collectors.groupingBy 代替 Collectors.toMap

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())
            )
    );

2
我认为,不必总是要不惜一切代价使用方法引用。在我看来,.flatMap(test -> test.map.entrySet().stream()).map(test -> test.map) .map(Map::entrySet) .flatMap(Collection::stream) 更简单。 - Holger
@Holger 我同意。我必须承认,我没有关注管道的那部分,只是保持原样,因为那不是问题所在。 - Eran

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