Java 流:获取按内部映射键分组的值

2022-09-03 13:29:45

我有,我想使用Java Streams从中获取它。Map<A, Map<B, C>>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给出一个StreamMap.Entry<B, C>
  • collect(Collectors.groupingBy(...))接受应用于并返回的函数,因此它将 的值收集到 。Map.Entry<B, C>BCList<C>

但它不会编译,从字面上看:

不能从静态上下文中引用非静态方法

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

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


答案 1

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

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

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

答案 2

流管道返回 一个 ,而不是一个 .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())));