【问题标题】:Java 8 stream - Merge maps and calculate average of "values"Java 8 流 - 合并映射并计算“值”的平均值
【发布时间】:2017-11-30 17:42:14
【问题描述】:

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

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

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

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

我有这段代码,但它给了我所有分数的 sum,而不是 averageInteger 类没有 average 方法) .

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>> 

有可能吗?

【问题讨论】:

    标签: java lambda java-8 java-stream


    【解决方案1】:

    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&lt;Long, List&lt;Integer&gt;&gt;

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

    【讨论】:

    • 我认为,并不总是需要不惜一切代价尝试使用方法引用。 .flatMap(test -&gt; test.map.entrySet().stream()).map(test -&gt; test.map) .map(Map::entrySet) .flatMap(Collection::stream) 简单,恕我直言
    • @Holger 我同意。我必须承认我并没有专注于管道的那一部分,而是保持原样,因为这不是问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-14
    • 2018-12-24
    • 2013-03-07
    • 2018-12-23
    • 1970-01-01
    相关资源
    最近更新 更多