79

私は Java 8 ラムダを使用Collectors toMapしており、 を返すために使用したいと考えていますSortedMap。私が思いつく最善の方法は、次のCollectors toMapメソッドをダミーmergeFunctionmapSupplier等号で呼び出すこと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ですか?

4

5 に答える 5

99

私はあなたがこれよりもはるかに良くなるとは思わない:

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

throwラムダは同じですが、throwingMerger()パッケージプライベートであるため、直接呼び出すことはできません(もちろん、throwingMerger()is. のような独自の静的メソッドをいつでも作成できます)。

于 2015-06-23T14:08:36.570 に答える
8

適切な API メソッドがないという dkatzel の確認に基づいて、私は独自のカスタム 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);
    }

}
于 2015-06-23T15:01:54.757 に答える
7

独自のthrowingMerger()メソッドを定義したり、明示的なラムダを使用したりせずにこれを行う標準的な方法はないようです。私の StreamEx ライブラリでは、独自のtoSortedMap使用throwingMerger()するメソッドを定義しました。

于 2015-06-23T16:26:35.757 に答える
5

これを行う別の方法は、Collectors.toMap() が返そうとするマップを返してから、それを新しい TreeMap<>() に渡すことです。

「hashCode()+equals()」と「compareTo」が一致している場合にのみ機能するという警告があります。それらが一貫していない場合、HashMap が TreeMap とは異なるキーのセットを削除することになります。

于 2015-06-23T16:48:54.930 に答える