J'utilise Java 8 lambdas et souhaite utiliser Collectors
toMap
pour renvoyer un SortedMap
. Le mieux que je puisse trouver est d’appeler la méthode Collectors
toMap
suivante avec une variable factice mergeFunction
et mapSupplier
égale à 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);
}
Cependant, je ne souhaite pas transmettre de fonction de fusion, car je ne souhaite que throwingMerger()
, de la même manière que l’implémentation de base toMap
comme suit:
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);
}
Quelle serait la méthode la plus pratique d’utiliser Collectors
pour renvoyer un SortedMap
?
Je ne pense pas que tu puisses aller beaucoup mieux que ça:
.collect(Collectors.toMap(keyMapper, valueMapper,
(v1,v2) ->{ throw new RuntimeException(String.format("Duplicate key for values %s and %s", v1, v2));},
TreeMap::new));
où throw
lambda est identique à throwingMerger()
mais je ne peux pas l'appeler directement car il s'agit d'un paquet privé (vous pouvez bien sûr toujours créer votre propre méthode statique comme celle de throwingMerger()
)
Sur la base de la confirmation par dkatzel qu'il n'y a pas de méthode API Nice, j'ai choisi de maintenir ma propre classe Collectors personnalisée:
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);
}
}
Il semble qu'il n'y ait pas de moyen standard de le faire sans définir votre propre méthode throwingMerger()
ou utiliser explicitement lambda. Dans ma bibliothèque StreamEx, j'ai défini la méthode toSortedMap
qui utilise également utilise my own throwingMerger()
.
Pour ce faire, vous pouvez également permettre à Collectors.toMap () de renvoyer la carte qu'il va renvoyer, puis de la transmettre à une nouvelle TreeMap <> ().
La mise en garde il est que cela ne fonctionne que si votre "hashCode () + equals ()" et "compareTo" sont cohérents. S'ils ne sont pas cohérents, alors HashMap supprimera un ensemble de clés différent de celui de votre TreeMap.
Si vous utilisez la bibliothèque goyave, vous pouvez utiliser:
.collect(ImmutableSortedMap.toImmutableSortedMap(comparator, keyMapper, valueMapper));
La carte obtenue sera une SortedMap
et sera également immuable.