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
CodePudding user response:
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);
CodePudding user response:
The most straightforward multi-map implementation using standard Java collections is a Map<K,List<V>>
- i.e. a map from each key to a list of values for that key. It is relatively trivial to add to it using
Map<String,List<Double>> multimap;
multimap.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
Finding the key with the minimum average is also trivial using a comparator to compare the averages:
Comparator<String> compareAverageKeys = Comparator.comparingDouble(
k -> multimap.get(k).stream().mapToDouble(v -> v).average().get());
multimap.keys().stream().min(compareAverageKeys);
If your only reason for creating the collection is to find the average then you could just keep the stats rather than the keys:
Map<String,DoubleSummaryStatistics> stats;
stats.computeIfAbsent(key, k -> new DoubleSummaryStatistics()).add(value);
Then finding the key with the minimum is much simpler and more efficient:
stats.keys().stream().min(Comparator.comparingDouble(k -> stats.get(k).getAverage());