sort java lambda java-8 java-stream collectors

Java 8 Collectors.toMap SortedMapa



sort map java 8 (4)

Basado en la confirmación de dkatzel de que no hay un buen método de API, he optado por mantener mi propia clase de coleccionistas personalizados:

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); } }

Estoy usando Java 8 lambdas y quiero usar Collectors toMap para devolver SortedMap . Lo mejor que se me ocurre es llamar al siguiente método Collectors toMap con un dummy mergeFunction y mapSupplier igual a 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); }

No quiero pasar una función de fusión, ya que solo quiero throwingMerger() , de la misma manera que la implementación básica de toMap siguiente manera:

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); }

¿Cuál sería el método de mejores prácticas para utilizar los Collectors para devolver un SortedMap ?


No creo que puedas ser mucho mejor que esto:

.collect(Collectors.toMap(keyMapper, valueMapper, (v1,v2) ->{ throw new RuntimeException(String.format("Duplicate key for values %s and %s", v1, v2));}, TreeMap::new));

donde throw lambda es lo mismo que throwingMerger() pero no puedo llamarlo directamente porque es un paquete privado (por supuesto, siempre puedes crear tu propio método estático para eso como throwingMerger() ).


Otra forma de hacerlo es permitir que Collectors.toMap () devuelva cualquier mapa que vaya a devolver, y luego pasarlo a un nuevo TreeMap <> ().

La advertencia es que esto solo funciona si tus "hashCode () + equals ()" y "compareTo" son consistentes. Si no son consistentes, terminará con el HashMap eliminando un conjunto diferente de claves que su TreeMap.


Parece que no hay una forma estándar de hacerlo sin definir tu propio método throwingMerger() o usar lambda explícito. En mi biblioteca StreamEx toSortedMap método toSortedMap que también uses mi propio throwingMerger() .