Как поясняется в этом ответе, это известная проблема, которая будет исправлена в 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
, относящийся к классу, в который вы поместили этот пользовательский сборщик.
person
Holger
schedule
23.11.2016