我有一个List<Foo>
想要一个Multimap<String, Foo>
我们将 Foo
分组到其中是他们的getId()
功能。
我正在使用 Java 8,它几乎非常棒,您可以执行以下操作:
List<Foo> foos = ...
Map<String, List<Foo>> foosById = foos.stream().collect(groupingBy(Foo::getId));
但是,我有大量代码需要 MultiMap<String, Foo>
所以这并没有为我节省任何东西,我又回到使用 for 循环来创建我的 Multimap
。我是否缺少一种很好的“功能”方式?
最佳答案
您可以只使用 Guava Multimaps
工厂:
ImmutableMultimap<String, Foo> foosById = Multimaps.index(foos, Foo::getId);
或将调用转至 Multimaps.index
与 Collector<T, A, R>
接口(interface)(如下所示,在未优化的简单实现中)。
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);
}
}
关于java - 从 Java 8 流创建 Guava Multimap 的最简洁方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23003542/