Java 8 Collectors.toMap SortedMap
Я использую Java 8 lambdas и хочу использовать Collectors
toMap
для возврата SortedMap
. Лучшее, что я могу придумать, - вызвать следующий метод Collectors
toMap
с фиктивным mergeFunction
и mapSupplier
равным TreeMap::new
.
public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier) {
BiConsumer<M, T> accumulator = (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}
Я не хочу передавать функцию слияния, хотя я просто хочу throwingMerger()
, так же как и базовая реализация toMap
следующим образом:
public static <T, K, U>
Collector<T, ?, Map<K, U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
Каким будет метод наилучшей практики использования Collectors
для возврата SortedMap
?
Ответы
Ответ 1
Я не думаю, что вы можете стать намного лучше, чем это:
.collect(Collectors.toMap(keyMapper, valueMapper,
(v1,v2) ->{ throw new RuntimeException(String.format("Duplicate key for values %s and %s", v1, v2));},
TreeMap::new));
где throw
lambda совпадает с throwingMerger()
, но я не могу напрямую называть это, поскольку он является закрытым пакетом (вы, конечно же, всегда можете создать свой собственный статический метод для этого типа throwingMerger()
.)
Ответ 2
Основываясь на подтверждении dkatzel, что нет хорошего API-метода, я решил сохранить свой собственный класс Collectors:
public final class StackOverflowExampleCollectors {
private StackOverflowExampleCollectors() {
throw new UnsupportedOperationException();
}
private static <T> BinaryOperator<T> throwingMerger() {
return (u, v) -> {
throw new IllegalStateException(String.format("Duplicate key %s", u));
};
}
public static <T, K, U, M extends Map<K, U>> Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper, Supplier<M> mapSupplier) {
return Collectors.toMap(keyMapper, valueMapper, throwingMerger(), mapSupplier);
}
}
Ответ 3
Кажется, что нет стандартного способа сделать это без определения вашего собственного метода throwingMerger()
или использования явной лямбды. В моей библиотеке StreamEx я определил метод toSortedMap
, который также использует мой собственный throwingMerger()
.
Ответ 4
Другой способ сделать это - разрешить Collectors.toMap() возвращать любую карту, которую он будет возвращать, а затем передать это новому элементу TreeMap < > ().
Опасность заключается в том, что это работает только в том случае, если ваши "hashCode() + equals()" и "compareTo" являются последовательными. Если они несовместимы, вы получите HashMap, удаляющий другой набор ключей, чем ваш TreeMap.