有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

函数式编程Java流映射列表的和值

我想确定“行”中“列”的数量,或者更好:构建地图列表的总和,如list>;排

是否有可能对每个不同列的所有值求和?函数应返回一个映射,列为键,所有值之和为值

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=总和。获取(“col1”)


共 (5) 个答案

  1. # 1 楼答案

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

    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 = new HashMap<>();
    mapList.forEach(map -> map.keySet().forEach(
                    s -> {
                        mapList.stream()
                               .collect(Collectors.groupingBy(foo -> s,
                                    Collectors.summingLong(foo -> map.get(s)))).forEach(
                                        (id, sumTargetCost) ->
                                                sum.put(s, sumTargetCost)
                        );
                    }
    
    ));
    
    Long sumVal1 = sum.get("col1"); // 270
    Long sumVal2 = sum.get("col2"); // 150
    Long sumVal3 = sum.get("col3"); // 30
    
    System.out.println("SumVal1: " + sumVal1 + ", SumVal2: " + sumVal2 + ", SumVal3: " + sumVal3);
    
  2. # 2 楼答案

    这不支持并行执行,但可以通过修改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. # 3 楼答案

    即使更改了值,也会给出相同的答案

  4. # 4 楼答案

    就这么简单

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

    霍尔格已经提供了一个清洁的解决方案,但我认为您也可以尝试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
        }
    }