I am new to java and lambda, I want to find the sum and average of values in a map of maps.
My object is like Map<String, Map<String, Double>> browserData;
Data is of the format
<Chrome, <UK, 2.90>>
<Chrome, <US, 5.20>>
<Chrome, <EU, -0.25>>
<IE, <UK, 0.1>>
<IE, <US, -.20>>
<IE, <EU, 0.00>>
<FF, <UK, 0.90>>
<FF, <US, 1.20>>
<FF, <EU, 1.25>>
The final result needs to be two maps, 1 for sum and another for average
map1 = <CountryName, SumValue>
map2 = <CountryName, AverageValue>
So the result of the above example it would be
map1 = <UK, 3.9>
<US, 6.2>
<EU, 1>
map2 = <UK, 1.3>
<US, 2.07>
<EU, 0.33>
How can I achieve this?
In Java 8, forEach statement can be used along with lambda expression that reduces the looping through a Map to a single statement and also iterates over the elements of a list. The forEach() method defined in an Iterable interface and accepts lambda expression as a parameter.
Loop a Map 1.1 Below is a normal way to loop a Map . 1.2 In Java 8, we can use forEach to loop a Map and print out its entries. 1.3 For the Map 's key or value containing null , the forEach will print null . P.S The normal way to loop a Map will print the same above output.
In Java HashMap, we can iterate through its keys, values, and key/value mappings.
The idea is to stream each of the entries of the inner maps and apply the appropriate collector to calculate the values you need:
Map<String, DoubleSummaryStatistics> stats = browserData.values().stream()
.flatMap(m -> m.entrySet().stream()) //Stream the inner maps' entrySets
.collect(groupingBy(Entry::getKey, summarizingDouble(Entry::getValue)));
DoubleSummaryStatistics ds = stats.getOrDefault("EU", new DoubleSummaryStatistics());
System.out.println("sumEu = " + ds.getSum());
System.out.println("avgEu = " + ds.getAverage());
If you do need the individual sum and average maps, you can create them from the summary map:
Map<String, Double> map1 = stats.entrySet().stream()
.collect(toMap(Entry::getKey, e -> e.getValue().getSum()));
Map<String, Double> map2 = stats.entrySet().stream()
.collect(toMap(Entry::getKey, e -> e.getValue().getAverage()));
note: I have used the following static imports:
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summarizingDouble;
import static java.util.stream.Collectors.toMap;
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