Java流对地图列表的值求和

时间:2018-09-12 11:58:57

标签: java functional-programming java-stream

我想确定“行”中或更“行”中“列”的取值:构建诸如List>行之类的地图列表的总和

是否可以对每个不同的列的所有值求和?该函数应返回一个Map,该列的键为键,所有值的总和为value。

summMap.get("columname")

假设我有以下地图列表:

List<Map<String, Long>> mapList = new ArrayList();
Map<String, Object> map1 = new HashMap<>();
Map<String, Object> map2 = new HashMap<>();
Map<String, Object> map3 = new HashMap<>();
map1.put("col1", 90);
map1.put("col2", 50);
map1.put("col3", 10);
map2.put("col1", 90);
map2.put("col2", 50);
map2.put("col3", 10);
map3.put("col1", 90);
map3.put("col2", 50);
map3.put("col3", 10);
mapList.add(map1);
mapList.add(map2);
mapList.add(map3);
Map<String, Long> sum = mapList.stream().distinct().sum() // Example
// result i'm awaiting/expecting
Long sumVal1 = sum.get("col1"); // 270
Long sumVal2 = sum.get("col2"); // 150
Long sumVal3 = sum.get("col3"); // 30

长sumVal = sum.get(“ col1”);

4 个答案:

答案 0 :(得分:3)

就这么简单

Map<String, Long> sum = mapList.stream()
    .flatMap(m -> m.entrySet().stream())
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Long::sum));

答案 1 :(得分:2)

Holger已经提供了一个干净解决方案,但我认为您也可以尝试使用flatMapgroupingBy作为

Map<String, Long> sum = mapList.stream().flatMap(map -> map.entrySet().stream())
                .collect(groupingBy(Map.Entry::getKey, summingLong(Map.Entry::getValue)));

您问题的整个解决方案:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.stream.Collectors.*;

public class ListMapSum {
    public static void main(String... args) {
        List<Map<String, Long>> mapList = new ArrayList();
        Map<String, Long> map1 = new HashMap<>();
        Map<String, Long> map2 = new HashMap<>();
        Map<String, Long> map3 = new HashMap<>();
        map1.put("col1", 90L);
        map1.put("col2", 50L);
        map1.put("col3", 10L);
        map2.put("col1", 90L);
        map2.put("col2", 50L);
        map2.put("col3", 10L);
        map3.put("col1", 90L);
        map3.put("col2", 50L);
        map3.put("col3", 10L);
        mapList.add(map1);
        mapList.add(map2);
        mapList.add(map3);
        Map<String, Long> sum = mapList.stream().flatMap(map -> map.entrySet().stream())
                .collect(groupingBy(Map.Entry::getKey, summingLong(Map.Entry::getValue)));
        Long sumVal1 = sum.get("col1"); // 270
        Long sumVal2 = sum.get("col2"); // 150
        Long sumVal3 = sum.get("col3"); // 30
    }
}

答案 2 :(得分:1)

这不支持并行执行,但是可以通过修改reduce中的最后一个参数来实现:

private static Map<String, Long> reduceLongs(List<Map<String, Long>> maps) {
    return maps.stream()
        .flatMap(map -> map.entrySet().stream())
        .reduce(new HashMap<>(), (map, e) -> {
            map.compute(e.getKey(), (k ,v) -> v == null ? e.getValue() : e.getValue() + v);
            return map;
        }, (m1, m2) -> { throw new UnsupportedOperationException(); });
}

和通过测试:

final List<Map<String, Long>> maps = new ArrayList<>();

Map<String, Long> map1 = new HashMap<>();
Map<String, Long> map2 = new HashMap<>();

map1.put("col1", 90L);
map1.put("col2", 50L);

map2.put("col1", 90L);
map2.put("col2", 50L);

map2.put("col3", 100L);

maps.add(map1);
maps.add(map2);

final Map<String, Long> sums = reduceLongs(maps);

assertEquals(180L, sums.get("col1").longValue());
assertEquals(100L, sums.get("col2").longValue());
assertEquals(100L, sums.get("col3").longValue());

答案 3 :(得分:0)

这是简单的解决方案,它将根据您的要求给出结果:

project2