guava java-8 java-stream

guava - Forma más limpia de crear una guagua MultiMap a partir de una secuencia java8



java-8 java-stream (1)

Puedes usar la fábrica de Guava Multimaps:

Multimaps.index(foos, Foo::getId);

o envuelva una llamada a Multimaps.index con una interfaz de recopilador (se muestra a continuación, en una implementación ingenua no optimizada).

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

y el Coleccionista:

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); } }

Tengo una List<Foo> y quiero un Multimap<String, Foo> donde hemos agrupado los Foo por su función getId() .

Estoy usando Java 8 y es casi increíble que puedas hacer:

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

Sin embargo, tengo una buena cantidad de código que quiere un MultiMap<String, Foo> así que esto no me salva nada y he vuelto a usar un for-loop para crear mi MultiMap. ¿Hay alguna buena forma "funcional" de la que me pierdo?