2

我已经在这个问题上沉思了一个星期,但我不太确定有什么方法可以做到这一点。我遇到的一个常见任务是为给定类型的值构建一个包含 ImmutableLists 的 ImmutableMap,例如ImmutableMap<K,ImmutableList<V>>,我想通过一个收集器来完成它,以便我可以在流上利用它。

我在下面显示的博客上找到了这个很棒的 ImmutableMap 收集器。但是我希望 V 成为一个 ImmutableList,并且我希望传入流映射多个具有相同键的值,该键与具有 ImmutableList 值的所述键配对。我尝试过的每一个实现都不是最理想的,而不是流式的,因为我一直在使用一个普通的 HashMap 保存 ImmutableList.Builder 值,当我完成填充时,我会遍历它并将其转换为 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 的帮助,我成功了!请参阅下面的答案。

4

1 回答 1

0

好吧,我想我成功地利用了 ImmutableListMultimap 来完成这个!谢谢fg!

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

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);
}
于 2014-12-14T20:17:30.870 回答