Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate though a Map of Maps with Lambda in Java 8?

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?

like image 390
victor Avatar asked Sep 16 '14 08:09

victor


People also ask

How do you iterate a map using lambda?

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.

How do I iterate a map using forEach in Java 8?

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.

Can you iterate through a HashMap Java?

In Java HashMap, we can iterate through its keys, values, and key/value mappings.


Video Answer


1 Answers

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;

like image 76
assylias Avatar answered Oct 19 '22 20:10

assylias