Потоки Java суммируют значения списка карт - PullRequest
0 голосов
/ 12 сентября 2018

Я хочу определить «столбцы» в «строках» или, что лучше: создать сумму из списка карт, например, «Список»> «Строки»

Можно ли как-то суммировать все значения каждого отдельного столбца? Функция должна возвращать карту со столбцом в качестве ключа и суммой всех значений в качестве значения.

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

Long sumVal = sum.get ("col1");

Ответы [ 4 ]

0 голосов
/ 13 сентября 2018

Хольгер уже предоставил чистое решение, но я думаю, что вы также можете попробовать flatMap и groupingBy как:

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
    }
}
0 голосов
/ 12 сентября 2018

Это не поддерживает параллельное выполнение, но можно сделать, изменив последний аргумент в 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());
0 голосов
/ 12 сентября 2018

Это так же просто, как

Map<String, Long> sum = mapList.stream()
    .flatMap(m -> m.entrySet().stream())
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Long::sum));
0 голосов
/ 12 сентября 2018

Вот простое решение, оно даст результат согласно вашему требованию:

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