Java8ストリームからguava MultiMapを作成する最もクリーンな方法[重複]
-
20-12-2019 - |
質問
私は持っています 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 ファクトリをそのまま使用できます。
Multimaps.index(foos, Foo::getId);
または、Collector インターフェイスを使用して Multimaps.index への呼び出しをラップします (以下に示すように、最適化されていない単純な実装で)。
Multimap<String, Foo> collect = foos.stream().collect(MultimapCollector.toMultimap(Foo::getId));
そしてコレクター:
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);
}
}
所属していません StackOverflow