79

我正在使用 Java 8 lambda,并希望使用它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使用返回 a的最佳实践方法是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));

其中throwlambda 是相同的,throwingMerger()但我不能直接调用它,因为它是包私有的(你当然可以总是为它创建自己的静态方法throwingMerger()。)

于 2015-06-23T14:08:36.570 回答
8

Based on dkatzel's confirmation that there's not a nice API method, I've opted for maintaining my own custom Collectors class:

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()如果不定义自己的方法或使用显式 lambda ,似乎没有标准的方法可以做到这一点。在我的 StreamEx 库中,我定义了toSortedMap使用我自己的throwingMerger().

于 2015-06-23T16:26:35.757 回答
5

另一种方法是允许 Collectors.toMap() 返回它将返回的任何地图,然后将其传递给新的 TreeMap<>()。

需要注意的是,这仅在您的“hashCode()+equals()”和“compareTo”一致时才有效。如果它们不一致,那么最终 HashMap 会删除与 TreeMap 不同的键集。

于 2015-06-23T16:48:54.930 回答
3

如果您使用番石榴库,那么您可以使用:

.collect(ImmutableSortedMap.toImmutableSortedMap(comparator, keyMapper, valueMapper));

生成的映射将是 aSortedMap并且也是不可变的。

于 2018-10-24T12:49:33.997 回答