Search code examples
javahashmapmultimap

How to calculate average from Collection of HashMap<String, Double>


I have a Collection of HashMap<String, Duble> which I am getting from multimap. I want to calculate the average on Maps values and calculate which Map key is having minimum average. The data looks like that:

HashMap<A1, 2.0>
HashMap<A2, 1.0>
HashMap<A1, 3.0>
HashMap<A2, 1.0>

I am not getting the idea. Can someone give me a hint?

Adding some more data which show why I am using MultiMap.

{‘Gateway’:’ G1’, ‘Device’: ‘D1’,’position’:{‘rssi’: 1}},
{‘Gateway’:’ G2’, ‘Device’: ‘D1’,’position’:{‘rssi’: 3}},
{‘Gateway’:’ G1’, ‘Device’: ‘D1’,’position’:{‘rssi’: 2}},
{‘Gateway’:’ G2’, ‘Device’: ‘D1’,’position’:{‘rssi’: 5}},
{‘Gateway’:’ G1’, ‘Device’: ‘D1’,’position’:{‘rssi’: 4}},
{‘Gateway’:’ G2’, ‘Device’: ‘D1’,’position’:{‘rssi’: 6}},
..
{‘Gateway’:’ G1’, ‘Device’: ‘D2’,’position’:{‘rssi’: 3}},
{‘Gateway’:’ G2’, ‘Device’: ‘D2’,’position’:{‘rssi’: 2}},

Actually, this is a series of data coming to my endpoint, I need to calculate Which device is staying more at which Gateway. First I need to add Devices into MultiMap and then Gateway with position into Map. In the end I want to calculate the average like that:

D1-> G1: {1,2,4} => 7/3 = 2.3 
D1-> G2: {3,5,6} => 14/3 = 4.6

Solution

  • Assuming your collection of maps is something similar to this:

    List<Map<String, Double>> mapList = List.of(
            Map.of("A1", 2.0),
            Map.of("A2", 1.0),
            Map.of("A1", 3.0),
            Map.of("A2", 1.0));
    

    You can just stream over the list (collection), stream over the entries of each map flatmaping to a stream of entries, collect to a new map grouping by key and averaging value, stream over the resulting map and find the min using a comparator by value:

    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.stream.Collectors;
    
    ....
    
    
    
    Entry<String, Double> entryWithMinAvg =
            mapList.stream()
                   .flatMap(m -> m.entrySet().stream())
                   .collect(Collectors.groupingBy(Entry::getKey, Collectors.averagingDouble(Entry::getValue)))
                   .entrySet()
                   .stream()
                   .min(Entry.comparingByValue())
                   .get();
    
    System.out.println(entryWithMinAvg);