Java 流:覆盖 return 类型的 Collectors.mapping

Java Streams: Override return type of Collectors.mapping

这是我的代码:

Map<String, Collection<? extends String>> test = listOfTipusIdentificadorPacient.stream()
    .collect(Collectors.groupingBy(
        TipusIdentificadorPacient::getOid,
        Collectors.mapping(TipusIdentificadorPacient::getUse, Collectors.toList())
    )
);

我收到这条编译消息:

Type mismatch: cannot convert from Map<String,List> to Map<String,Collection<? extends String>>

我不太明白如何覆盖 Collectors.mapping 以便:

return:
  Map<String,Collection<? extends String>>
instead of:
  Map<String,List<String>>

我已经尝试创建另一个通用代码以使其能够编译。

代码是:

Stream<Map.Entry<String, String>> streamOfPairedStrings = Stream.of();
Map<String, Collection<? extends String>> test = streamOfPairedStrings
    .collect(Collectors.groupingBy(
        Map.Entry::getKey,
        Collectors.mapping(Pair::getValue, Collectors.toList())
    )
);

有什么想法吗?

编译错误的原因是:

Map<String, List<String>> mapOfLists = Map.of();
Map<String, Collection<? extends String>> mapOfCollections = Map.of();

考虑到此代码将是合法的:

mapOfCollections.put("", Set.of());

也就是说,您可以在值不是 List<String> 的地方放置 key/value 对。因此,您不能分配:

mapOfCollections = mapOfLists;

因为那样你就可以执行上面的 put,导致堆污染。编译器只是阻止你这样做。

// If it were legal...
mapOfCollections = mapOfLists;
mapOfCollections.put("", Set.of());
List<String> list = mapOfLists.get(""); // ClassCastException!

我认为您可以在 toList() 周围使用 Collectors.collectingAndThen 来做到这一点,其中“然后”是一个不受约束的转换:

Collectors.collectingAndThen(Collectors.toList(), a -> a)

您不能使用 Function.identity() 执行此操作的原因是 collectingAndThenFunction.identity() 的签名组合:

  • collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher) 表示函数的输入类型必须与收集器的输出类型匹配 - 在您的情况下,List<String>.
  • Function.identity()Function<T, T>(没有通配符)。由于函数的输入类型必须是List<String>,它的输出类型也是List<String>.

a -> a 看起来像恒等函数,但实际上比它更通用:它是一个向上转换函数,Function<? extends T, T>,意味着输出类型不必须与输入完全相同,但可以安全地进行转换。

因此,在这里,a -> a充当Function<List<String>, Collection<? extends String>>(因为List<String>Collection<String>的子类型,而Collection<? extends String>Collection<? extends String>的子类型) .