Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guava: how to customly reduce a multimap?

Tags:

java

guava

Is the concept of reduce implemented in Guava libs? I mean I have a multimap:

[1] -> 1, 2, 5, 8
[2] -> 3, 6, 4
[3] -> 1, 0

Then I have a multiplying function:

(a, b) -> a * b

And I want to get the following map:

[1] -> 80          // 1 * 2 * 5 * 8
[2] -> 72          // 3 * 6 * 4
[3] -> 0           // 1 * 0

How do I do it in Guava?

like image 308
Denis Kulagin Avatar asked Oct 19 '15 12:10

Denis Kulagin


People also ask

What is Multimap guava?

A Multimap is a new collection type that is found in Google's Guava library for Java. A Multimap can store more than one value against a key. Both the keys and the values are stored in a collection, and considered to be alternates for Map<K, List<V>> or Map<K, Set<V>> (standard JDK Collections Framework).

Does Multimap maintain order?

Multimap is similar to a map with the addition that multiple elements can have the same keys. Also, it is NOT required that the key-value and mapped value pair have to be unique in this case. One important thing to note about multimap is that multimap keeps all the keys in sorted order always.

What is ImmutableListMultimap?

ImmutableListMultimap.Builder<K,V>A builder for creating immutable ListMultimap instances, especially public static final multimaps ("constant multimaps").

What is TreeMultimap?

The TreeMultimap is a variation of a Map in which multiple values or objects are associated with a single key but it will return a sorted list of objects according to their natural ordering without any duplicate key/value pairs.


1 Answers

I don't think there is a reduction operation in Guava. I guess you have two options.

If you're using java-8, just stream over the entry set, and collect the entries into a new map with groupingBy and reduce.

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.reducing;

...

Map<Integer, Integer> map = 
    multimap.entries()
            .stream()
            .collect(groupingBy(Map.Entry::getKey,
                                reducing(1, Map.Entry::getValue, (a, b) -> a * b)));

groupingBy as you can guess, will group the entries by their key values. Then we just reduce the values grouped (which are Entry<Integer, Integer>) by first mapping their to their values and finally by multiplying them - providing the identity value which is 1 for the multiplication.


If you can't use java-8, you can get back a Map<Integer, Collection<Integer>> from your Multimap with Multimaps.asMap and use Maps.transformValues:
Map<Integer, Collection<Integer>> tempMap = Multimaps.asMap(oldMap);
Map<Integer, Integer> newMap = 
    Maps.transformValues(tempMap, new Function<Collection<Integer>, Integer>() {
            @Nullable
            @Override
            public Integer apply(Collection<Integer> input) {
                //do the multiplication here
                return 0;
            }
        });
like image 160
Alexis C. Avatar answered Oct 09 '22 00:10

Alexis C.