按Java 8中的Map列表分组

时间:2015-12-09 08:59:38

标签: java lambda java-8 java-stream

我有一个像这样的列表:

List<Map<String, Long>>

有没有办法,使用lambda,将此列表转换为:

Map<String, List<Long>>

示例:

Map<String, Long> m1 = new HashMap<>();
m1.put("A", 1);
m1.put("B", 100);

Map<String, Long> m2 = new HashMap<>();
m2.put("A", 10);
m2.put("B", 20);
m2.put("C", 100);

List<Map<String, Long>> beforeFormatting = new ArrayList<>();
beforeFormatting.add(m1);
beforeFormatting.add(m2);

格式化后:

Map<String, List<Long>> afterFormatting;

看起来像:

A -> [1, 10]
B -> [100, 20]
C -> [100]

1 个答案:

答案 0 :(得分:14)

您需要flatMap每个地图的条目集来创建Stream<Map.Entry<String, Long>>。然后,可以使用groupingBy(classifier, downstream)收集器收集此Stream:分类器返回条目的键,下游收集器将条目映射到其值并将其收集到List

Map<String, List<Long>> map = 
     list.stream()
         .flatMap(m -> m.entrySet().stream())
         .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));

此代码需要以下静态导入:

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;

完整的例子:

public static void main(String[] args) {
    Map<String, Long> m1 = new HashMap<>();
    m1.put("A", 1l);
    m1.put("B", 100l);

    Map<String, Long> m2 = new HashMap<>();
    m2.put("A", 10l);
    m2.put("B", 20l);
    m2.put("C", 100l);

    List<Map<String, Long>> beforeFormatting = new ArrayList<>();
    beforeFormatting.add(m1);
    beforeFormatting.add(m2);

    Map<String, List<Long>> afterFormatting =
        beforeFormatting.stream()
                        .flatMap(m -> m.entrySet().stream())
                        .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));

    System.out.println(afterFormatting); // prints {A=[1, 10], B=[100, 20], C=[100]}
}