Java 收集器中缺少键、值和映射供应商的toMap方法

Java 收集器中缺少键、值和映射供应商的toMap方法,java,java-8,Java,Java 8,Collectors.toMap有三个重载变量 1。键和值映射器: toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, Bin

Collectors.toMap
有三个重载变量

1。键和值映射器:

toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction)
toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)
或者,使用
Collectors.collectingAndThen

persons.stream()
        .collect(Collectors.collectingAndThen(Collectors.toMap(Person::getId, Function.identity()),
                LinkedHashMap::new));
编辑:

正如@Holger在评论中指出的,复制到
LinkedHashMap
不会有帮助,因为在使用toMap方法填充地图时,顺序已经改变

[…]collectingAndThen无法实现目标,因为在事实发生后将无序映射复制到LinkedHashMap不会恢复顺序


显然,您的第二种方法实现了解决方案,并传达了拥有新地图类型的意图。为什么在完全没有必要的情况下污染API?@Avi-True。但是传递合并函数会错误地向读卡器指示源可以有重复的ID(或者通常键映射器可以从源生成重复的ID)。第二个选项更详细一点,第一个选项我不会做,因为它误导了读者。第二种选择是精确的。冗长通常不是污染API的充分理由。这不是一个不合理的要求(Guava的
ImmutableMap.toImmutableMap(…)
collector会这样做);问题在于,这是否是一个足够有用的要求,足以在标准API中体现其重要性。太容易高估我们自己的想法对其他人的有用性(我们都可能为此感到内疚)。@Avi
收集然后
无法实现目标,因为在事实发生后将无序的地图复制到
LinkedHashMap
并不能恢复秩序。但是使用
(a,b)->a
作为合并函数的另一个变体也不等效,因为没有合并函数的
toMap
收集器将对重复的键抛出异常。由于merge函数不知道键,因此无法以这种方式实现预期的行为。这是一个问题,即使是JDK开发人员也没有意识到,因此在JDK 8中,它会产生错误的错误消息。另见…
persons.stream()
        .collect(Collectors.collectingAndThen(Collectors.toMap(Person::getId, Function.identity()),
                LinkedHashMap::new));