I am frequently running into situations where I need a map of multi-maps for the sake of efficiency. I'd prefer to use Guava's ImmutableMap
and ImmutableMultimap
to accomplish this.
I have borrowed and created several Collector
implementations for Guava so I can leverage Java 8 streams. For example, here is a collector for an ImmutableListMultimap
.
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) -> l.putAll(r.build());
Function<ImmutableListMultimap.Builder<K, V>, ImmutableListMultimap<K, V>> finisher = ImmutableListMultimap.Builder::build;
return Collector.of(supplier, accumulator, combiner, finisher);
}
I would like to create a very similar Collector for my current problem. I want my collector to create an ImmutableMap<P,ImmutableMultimap<C,V>>
, where P
is the parent key of the main map and C
is the child key of the child map. Two Function
lambdas would be provided to map these keys for each T
item.
This is much easier said than done. All I did productive so far is create the method stub.
public static <T, P, C, V> Collector<T, ?, ImmutableMap<P, ImmutableMultimap<C,V>>> toPartitionedImmutableMultimap(
Function<? super T, ? extends P> parentKeyMapper,
Function<? super T, ? extends C> childKeyMapper,
Function<? super T, ? extends V> valueMapper) {
}
Because the Guava immutable collection builders do not allow lookups, I found myself using mutable hashmaps to be able to look up previously captured values so I would only create a new ImmutableMultimap when the P key was absent. But this process became dizzying very quickly.
Is there an efficient way to do this?
Have you tried the straightforward approach?
collectingAndThen(
groupingBy(
parentKeyMapper,
toImmutableListMultimap(childKeyMapper, valueMapper)
),
ImmutableMap::copyOf
);
Update: Above code works fine with JDK but Eclipse compiler is complaining about it. Here's a version that Eclipse will accept:
public static <T, P, C, V> Collector<T, ?, ImmutableMap<P, ImmutableMultimap<C, V>>> toPartitionedImmutableMultimap(
Function<? super T, ? extends P> parentKeyMapper,
Function<? super T, ? extends C> childKeyMapper,
Function<? super T, ? extends V> valueMapper) {
return Collectors.collectingAndThen(
Collectors.groupingBy(
parentKeyMapper,
SO29417692.<T,C,V>toImmutableListMultimap(childKeyMapper, valueMapper)
),
ImmutableMap::<P,ImmutableMultimap<C,V>>copyOf
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With