Guava: how to reduce the number of multimaps?

Is the reduction concept implemented in Guava libs? I mean, I have multimap:

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

Then I have a multiplication function:

 (a, b) -> a * b 

And I want to get the following card:

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

How to do it in Guava?

+6
source share
3 answers

I do not think that there is a reduction operation in Guava. I think you have two options.

If you are using java-8 , just go through the recordset and collect the records into a new map using 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 might guess, groups records by their key values. Then we simply summarize the values โ€‹โ€‹grouped (which are Entry<Integer, Integer> ), first matching them with their values โ€‹โ€‹and finally by multiplying them, providing an identity value of 1 for the multiplication.

<h / "> If you cannot use , you can return Map<Integer, Collection<Integer>> from Multimap using 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; } }); 
+5
source

String and List<Integer> as values.

You can also try something like

  Map<String, List<Integer>> test = new HashMap<String, List<Integer>>(); test.put("a", Lists.newArrayList(1, 2, 3)); test.put("b", Lists.newArrayList(4, 5, 6)); Map<String, Integer> transformEntries = Maps.transformEntries(test, new EntryTransformer<String, List<Integer>, Integer>() { @Override public Integer transformEntry(String key, List<Integer> values) { Integer a = 1; for (Integer value : values) { a = value * a; } return a; } }); System.out.println(transformEntries); 

Result: {a = 6, b = 120}

Maps.EntryTransformer

+1
source

The easiest way is to use the stream on top of entries() and map the function above it, which converts the collection into a stream and runs the appropriate reduce() function for it.

Something like that:

 HashMap<Integer, Integer> collected = mmap.entries().stream().collect(HashMap::new, (map, e) -> { map.put(e.getKey(), e.getValue().stream().reduce((a, b) -> (a * b)).get()); }, HashMap::putAll); 
0
source

All Articles