Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate and work on the values of a map whose values are a list of elements using java 8 streams and lambdas

Gist: We are trying to rewrite our old java code with java 8 streams and lambdas wherever possible.

Question: I have a map whose key is a string and values are list of user defined objects.

Map<String, List<Person>> personMap = new HashMap<String, List<Person>>();
personMap.put("A", Arrays.asList(person1, person2, person3, person4));
personMap.put("B", Arrays.asList(person5, person6, person7, person8));

Here the persons are grouped based on their name's starting character.

I want to find the average age of the persons on the list for every key in the map.

For the same, i have tried many things mentioned in stackoverflow but none is matching with my case or few are syntactically not working.

Thanks In Advance!

like image 752
Saravana Kumar M Avatar asked Dec 21 '25 10:12

Saravana Kumar M


2 Answers

You didn't specify how (or if) you would like the ages to be stored, so I have it as just a print statement at the moment. Nevertheless, it's as simple as iterating over each entry in the Map and printing the average of each List (after mapping the Person objects to their age):

personMap.forEach((k, v) -> {
    System.out.println("Average age for " + k + ": " + v.stream().mapToInt(Person::getAge).average().orElse(-1));
});

If you would like to store it within another Map, then you can collect it to one pretty easily:

personMap.entrySet()
         .stream()
         .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
                                                            .stream()
                                                            .mapToInt(Person::getAge)
                                                            .average()
                                                            .orElse(-1)));

Note: -1 is returned if no average is present, and this assumes a getter method exists within Person called getAge, returning an int.

like image 107
Jacob G. Avatar answered Dec 23 '25 22:12

Jacob G.


You can do it like so:

// this will get the average over a list
Function<List<Person>, Double> avgFun = (personList) ->
   personList.stream()
      .mapToInt(Person::getAge)
      .average()
      .orElseGet(null);

// this will get the averages over your map
Map<String, Double> result = personMap.entrySet().stream()
   .collect(Collectors.toMap(
      Map.Entry::getKey,
      entry -> avgFun.apply(entry.getValue())
   ));
like image 43
Stefan Zhelyazkov Avatar answered Dec 23 '25 23:12

Stefan Zhelyazkov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!