正如 this answer 中所解释的,这是一个已知问题,将在 Java 9 中修复 - 至少对于不接受合并函数的 toMap 收集器而言。
由于合并函数只接收要合并的两个值,并且签名不能轻易更改,因此这些重载方法目前还没有修复。不幸的是,没有toMap 收集器接受Map Supplier 而没有明确的合并功能,因此除非在发布之前这会发生变化,否则将无法解决您应该返回LinkedHashMap 的场景。
所以解决方案是实现自己的收集器。然后,您不必等待 Java 9,也不必冒险失望。
static <T, K, V, M extends Map<K, V>> Collector<T, ?, M> toMap(
Function<T, K> keyExtractor, Function<T, V> valueExtractor, Supplier<M> mapSupplier) {
return Collector.of(mapSupplier,
(m, t) -> putUnique(m, keyExtractor.apply(t), valueExtractor.apply(t)),
(m1,m2)-> { m2.forEach((k, v) -> putUnique(m1, k, v)); return m1; }
);
}
private static <K,V> void putUnique(Map<K,V> map, K key, V v1){
V v2 = map.putIfAbsent(key, v1);
if(v2 != null) throw new IllegalStateException(
String.format("Duplicate key %s (values %s and %s)", key, v1, v2));
}
你可以把这个收集器当作
LinkedHashMap<KeyType, ValueType> map = myList.stream()
.collect(toMap(MyObject::getKey, MyObject::getValue, LinkedHashMap::new));
或使用合格的MyCollector.toMap,指的是您放置自定义收集器的类。