【问题标题】:Java streams sum values of a List of MapsJava 流对 Map 列表的值求和
【发布时间】:2019-02-17 01:31:07
【问题描述】:

我想确定“行”中的“列”或更好:构建地图列表的总和,如 List> 行

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

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

【问题讨论】:

  • 显示你得到的代码。
  • 您的问题不清楚 - 请重新表述您的问题。
  • 因此您有一个映射列表为 ("columnname","value") 并且您希望每个唯一列名的 [value] 总和。对吗?
  • 我添加了一个例子
  • 是的,对于每个唯一的列。

标签: java functional-programming java-stream


【解决方案1】:

即使在更改值之后也会给出相同的答案

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:

Holger 已经提供了 clean 解决方案,但我认为您也可以尝试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
    }
}

【讨论】:

    【解决方案3】:

    就这么简单

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

    【讨论】:

      【解决方案4】:

      这不支持并行执行,但可以通过修改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());
      

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-09-01
          • 1970-01-01
          • 2018-03-03
          • 2018-06-07
          • 1970-01-01
          • 2012-09-11
          • 2020-07-05
          • 1970-01-01
          相关资源
          最近更新 更多