15

我有Map<A, Map<B, C>>并且我想Map<B, List<C>>使用 Java Streams 从中获得。

我尝试按如下方式进行:

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,因此它收集Cinto的值List<C>

但它不会编译,字面意思是:

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

Map.Entry::getKey最后一行。

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

4

2 回答 2

14

您的 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())
            ));
}
于 2016-01-11T11:11:12.597 回答
8

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

要获得什么 a Map<B, List<C>>,您需要添加一个mapping将映射Map.Entry<B,C>到的 a C

return input.entrySet()
        .stream()
        .flatMap(it -> it.getValue().entrySet().stream())
        .collect(Collectors.groupingBy(Map.Entry::getKey,Collectors.mapping(Map.Entry::getValue,Collectors.toList())));
于 2016-01-11T11:10:04.537 回答