从 Java 8 流创建番石榴多地图的最简洁方法

2022-08-31 13:02:11

我有一个,想要一个我们按其功能对's进行分组的地方。List<Foo>Multimap<String, Foo>FoogetId()

我正在使用Java 8,它几乎很棒,因为你可以做到:

List<Foo> foos = ...
Map<String, List<Foo>> foosById = foos.stream().collect(groupingBy(Foo::getId));

但是,我有大量的代码想要一个,所以这并不能为我节省任何东西,我又回到了使用for循环来创建我的.有没有一个很好的“功能”方式,我错过了?MultiMap<String, Foo>Multimap


答案 1

您只需使用番石榴多地图工厂:

ImmutableMultimap<String, Foo> foosById = Multimaps.index(foos, Foo::getId);

或者用接口包装对 Multimaps.index 的调用(如下所示,在未优化的朴素实现中)。Collector<T, A, R>

Multimap<String, Foo> collect = foos.stream()
        .collect(MultimapCollector.toMultimap(Foo::getId));

和 :Collector

public class MultimapCollector<T, K, V> implements Collector<T, Multimap<K, V>, Multimap<K, V>> {

    private final Function<T, K> keyGetter;
    private final Function<T, V> valueGetter;

    public MultimapCollector(Function<T, K> keyGetter, Function<T, V> valueGetter) {
        this.keyGetter = keyGetter;
        this.valueGetter = valueGetter;
    }

    public static <T, K, V> MultimapCollector<T, K, V> toMultimap(Function<T, K> keyGetter, Function<T, V> valueGetter) {
        return new MultimapCollector<>(keyGetter, valueGetter);
    }

    public static <T, K, V> MultimapCollector<T, K, T> toMultimap(Function<T, K> keyGetter) {
        return new MultimapCollector<>(keyGetter, v -> v);
    }

    @Override
    public Supplier<Multimap<K, V>> supplier() {
        return ArrayListMultimap::create;
    }

    @Override
    public BiConsumer<Multimap<K, V>, T> accumulator() {
        return (map, element) -> map.put(keyGetter.apply(element), valueGetter.apply(element));
    }

    @Override
    public BinaryOperator<Multimap<K, V>> combiner() {
        return (map1, map2) -> {
            map1.putAll(map2);
            return map1;
        };
    }

    @Override
    public Function<Multimap<K, V>, Multimap<K, V>> finisher() {
        return map -> map;
    }

    @Override
    public Set<Characteristics> characteristics() {
        return ImmutableSet.of(Characteristics.IDENTITY_FINISH);
    }
}

答案 2

Guava 21.0 引入了几种返回 Collector 实例的方法,这些实例将 a 转换为按对其元素应用函数的结果分组的方法。这些方法是:StreamMultimap

ImmutableListMultimap<String, Foo> foosById = foos.stream().collect(
        ImmutableListMultimap.toImmutableListMultimap(
                Foo::getId, Function.identity()));
ImmutableSetMultimap<String, Foo> foosById = foos.stream().collect(
        ImmutableSetMultimap.toImmutableSetMultimap(
                Foo::getId, Function.identity()));
HashMultimap<String, Foo> foosById = foos.stream().collect(
        Multimaps.toMultimap(
                Foo::getId, Function.identity(), HashMultimap::create)
);

推荐