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

Mar*_*tin 4 java lambda java-8 java-stream

假设我有一个List每个都有一个类的类Map.

public class Test {
    public Map<Long, Integer> map;
}
Run Code Online (Sandbox Code Playgroud)

时间戳中的LongMapInteger值是分数.

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

我有这个代码,但它给了我所有分数的总和而不是平均值(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);
Run Code Online (Sandbox Code Playgroud)

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

Map<Long, List<Integer>> 
Run Code Online (Sandbox Code Playgroud)

有可能吗?

Era*_*ran 7

而不是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)
                )
        );
Run Code Online (Sandbox Code Playgroud)

哦,即使你可能不再需要它,你也可以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())
            )
    );
Run Code Online (Sandbox Code Playgroud)

  • 我认为,并不总是需要不惜一切代价尝试使用方法引用.`.flatMap(test - > test.map.entrySet().stream())`比`.map(test - > test.map).map(Map :: entrySet).flatMap(Collection :: stream)简单`,imho (2认同)