创建一个高效的ImmutableMap收集器,它为每个键保存一个ImmutableList

时间:2014-12-14 19:32:33

标签: java stream guava immutability collectors

我一直在沉思这一周,我不太确定如何做到这一点。我遇到的一个常见任务是构建包含ImmutableLists的ImmutableMap,如ImmutableMap<K,ImmutableList<V>>中所示,对于给定类型的值,我想通过收集器来完成,这样我就可以在流上使用它。 / p>

我在下面的博客上发现了这个伟大的ImmutableMap收藏家。但我希望V是一个ImmutableList,我希望传入的流映射多个值,使用与ImmutableList值配对的相同密钥。我尝试过的每个实现都是次优的而不是像流一样,因为我继续使用保存ImmutableList.Builder值的普通HashMap,当我完成填充时,我会遍历它并将其转换为ImmutableList值调用build()并将其放入新映射中。有什么想法吗?

public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>>
    toImmutableMap(
        Function<? super T, ? extends K> keyMapper,
        Function<? super T, ? extends V> valueMapper) {

    Supplier<ImmutableMap.Builder<K, V>> supplier =
        ImmutableMap.Builder::new;

    BiConsumer<ImmutableMap.Builder<K, V>, T> accumulator =
         (b, t) -> b.put(keyMapper.apply(t), valueMapper.apply(t));

    BinaryOperator<ImmutableMap.Builder<K, V>> combiner =
         (l, r) -> l.putAll(r.build());

    Function<ImmutableMap.Builder<K, V>, ImmutableMap<K, V>> finisher =
       ImmutableMap.Builder::build;

    return Collector.of(supplier, accumulator, combiner, finisher);
}

我希望实现有一个标题...

public static <T, K, V> Collector<T, ?, ImmutableMap<K, ImmutableList<V>>>

感谢fge的帮助,我成功了!见下面的答案。

1 个答案:

答案 0 :(得分:0)

好吧,我想我成功利用了ImmutableListMultimap来实现这一目标!谢谢fge!

如果有人看到任何可以改进的东西(我认为合并器无法优化但是如果我错了就纠正我),请告诉我。

public static <T, K, V> Collector<T, ?, ImmutableListMultimap<K, V>> toImmutableListMultimap(
        Function<? super T, ? extends K> keyMapper,
        Function<? super T, ? extends V> valueMapper) {

    Supplier<ImmutableListMultimap.Builder<K, V>> supplier = ImmutableListMultimap.Builder::new;

    BiConsumer<ImmutableListMultimap.Builder<K, V>, T> accumulator = (b, t) -> b
            .put(keyMapper.apply(t), valueMapper.apply(t));

    BinaryOperator<ImmutableListMultimap.Builder<K, V>> combiner = (l, r) -> { 
        final ImmutableListMultimap<K, V> rightMap = r.build();
        rightMap.keySet().stream().forEach(k -> l.putAll(k, rightMap.get(k)));
        return l;
    };

    Function<ImmutableListMultimap.Builder<K, V>, ImmutableListMultimap<K, V>> finisher = ImmutableListMultimap.Builder::build;

    return Collector.of(supplier, accumulator, combiner, finisher);
}

更新 - 反映fge的建议并简化组合器

public static <T, K, V> Collector<T, ?, ImmutableMultimap<K, V>> toImmutableListMultimap(
        Function<? super T, ? extends K> keyMapper,
        Function<? super T, ? extends V> valueMapper) {

    Supplier<ImmutableMultimap.Builder<K, V>> supplier = ImmutableListMultimap.Builder::new;

    BiConsumer<ImmutableMultimap.Builder<K, V>, T> accumulator = (b, t) -> b
            .put(keyMapper.apply(t), valueMapper.apply(t));

    BinaryOperator<ImmutableMultimap.Builder<K, V>> combiner = (l, r) -> l.putAll(r.build());

    Function<ImmutableMultimap.Builder<K, V>, ImmutableMultimap<K, V>> finisher = ImmutableMultimap.Builder::build;

    return Collector.of(supplier, accumulator, combiner, finisher);
}