如何使用Java Streams API合并Map列表和Lists值?

taf*_*it3 4 java java-8 java-stream

如何Map<X, List<String>>通过Xp 减少分组并同时加入所有列表值,这样我最后会有Map<Integer, List<String>>什么?

这是我到目前为止所尝试的:

class X {
    int p;
    int q;
    public X(int p, int q) { this.p = p; this.q = q; }
}
Map<X, List<String>> x = new HashMap<>();
x.put(new X(123,5), Arrays.asList("A","B"));
x.put(new X(123,6), Arrays.asList("C","D"));
x.put(new X(124,7), Arrays.asList("E","F"));
Map<Integer, List<String>> z = x.entrySet().stream().collect(Collectors.groupingBy(
    entry -> entry.getKey().p, 
    mapping(Map.Entry::getValue, 
        reducing(new ArrayList<>(), (a, b) -> { a.addAll(b); return a; }))));
System.out.println("z="+z);
Run Code Online (Sandbox Code Playgroud)

但结果是:z = {123 = [E,F,A,B,C,D],124 = [E,F,A,B,C,D]}.

我想要z = {123 = [A,B,C,D],124 = [E,F]}

Era*_*ran 5

以下是使用两个Stream管道执行此操作的一种方法:

Map<Integer, List<String>> z = 
// first process the entries of the original Map and produce a 
// Map<Integer,List<List<String>>>
    x.entrySet()
     .stream()
     .collect(Collectors.groupingBy(entry -> entry.getKey().p, 
                                    mapping(Map.Entry::getValue,
                                            toList())))
// then process the entries of the intermediate Map and produce a 
// Map<Integer,List<String>>
     .entrySet()
     .stream()
     .collect (toMap (Map.Entry::getKey,
                      e -> e.getValue()
                            .stream()
                            .flatMap(List::stream)
                            .collect(toList())));
Run Code Online (Sandbox Code Playgroud)

Java 9应该添加一个flatMapping收集器,这将使您的生活更轻松(感谢Holger,我了解了这个新功能).

输出:

z={123=[A, B, C, D], 124=[E, F]}
Run Code Online (Sandbox Code Playgroud)