Java Streams:获取按内部映射键

时间:2016-01-11 11:02:24

标签: java java-8 grouping java-stream collectors

我有Map<A, Map<B, C>>,我希望使用Java Streams从中获取Map<B, List<C>>

我尝试按如下方式进行:

public <A, B, C> Map<B, List<C>> groupsByInnerKey(Map<A, Map<B, C>> input) {
    return input.values()
            .stream()
            .flatMap(it -> it.entrySet().stream())
            .collect(Collectors.groupingBy(Map.Entry::getKey));
}

我的期望:

  • flatMap提供Stream Map.Entry<B, C>
  • collect(Collectors.groupingBy(...))获取应用于Map.Entry<B, C>并返回B的函数,因此会将C的值收集到List<C>

但它根本没有编译:

  

无法从静态上下文引用非静态方法

在最后一行的Map.Entry::getKey

有人可以解释什么是错的或者什么是实现我想要的正确方法?

2 个答案:

答案 0 :(得分:12)

您的Stream由Map.Entry个对象组成,但是您希望收集的实际上是条目的值,而不是条目本身。使用当前代码,您将获得Map<B, List<Map.Entry<B, C>>>

因此,您只是错过了对Collectors.mapping的来电。此收集器将使用给定的映射器函数映射Stream元素,并将该结果收集到下游容器中。在这种情况下,映射器为Map.Entry::getValue(因此返回映射条目中的值),下游收集器收集到List

public <A, B, C> Map<B, List<C>> groupsByInnerKey(Map<A, Map<B, C>> input) {
    return input.values()
            .stream()
            .flatMap(it -> it.entrySet().stream())
            .collect(Collectors.groupingBy(
                 Map.Entry::getKey,
                 Collectors.mapping(Map.Entry::getValue, Collectors.toList())
            ));
}

答案 1 :(得分:7)

您的流管道返回Map<B, List<Map.Entry<B,C>>>,而不是Map<B, List<C>>

要获得Map<B, List<C>>的内容,您需要添加mappingMap.Entry<B,C>映射到C

return input.entrySet()
        .stream()
        .flatMap(it -> it.getValue().entrySet().stream())
        .collect(Collectors.groupingBy(Map.Entry::getKey,Collectors.mapping(Map.Entry::getValue,Collectors.toList())));