Reputation: 63
I need the average of the list
List<Measurement> measurements = new ArrayList<>();
Measurement m1 = new Measurement();
Map<String,Double> map1 = new HashMap<>();
map1.put("age",18.0);
map1.put("score",88.0);
map1.put("rating",5.0);
m1.setMetric(map1);
Measurement m2 = new Measurement();
Map<String,Double> map2 = new HashMap<>();
map2.put("age",21.0);
map2.put("score",null);
map2.put("rating",23.0);
m2.setMetric(map2);
Measurement m3 = new Measurement();
Map<String,Double> map3 = new HashMap<>();
map3.put("age",31.0);
map3.put("score",32.0);
map3.put("rating",null );
m3.setMetric(map3);
measurements.add(m1);
measurements.add(m2);
measurements.add(m3);
How do I get the average Age for the above list of maps. Also Average Score by ignoring the null values.
Any help would be really appreciated. I am struggling to fix since 3 days. Thank you in advance.
Upvotes: 3
Views: 1118
Reputation: 5362
for such Measurement
class:
class Measurement {
Map<String, Double> map;
public void setMetric(Map<String, Double> map) {
this.map = map;
}
}
Double averageAge = measurements.stream()
.collect(Collectors.averagingDouble(node -> node.map.getOrDefault("age", 0D)));
And stream for nullable "score":
Double averageAge = measurements.stream()
.filter(node -> node.map.get("score") != null)
.collect(Collectors.averagingDouble(node -> node.map.getOrDefault("score", 0D)));
In above code you have node.map
where map
is field form class. Can be replaced with getMap()
or different method returning value (which you are set by setMetric()
)
Double average = 0D;
for (Measurement measure : measurements) {
average += measure.map.getOrDefault("age", 0D);
}
average /= measurements.size();
Double average = 0D;
int counter = 0;
for (Measurement measure : measurements) {
if (measure.map.get("score") != null) {
average += measure.map.getOrDefault("score", 0D);
counter++;
}
}
average /= counter;
Double min = Double.MAX_VALUE;
for (Measurement measure : measurements) {
Double score = measure.map.get("score");
if (score != null && score < min) {
min = score;
}
}
System.out.println(min);
Double max = measurements.stream()
.filter(node -> node.map.get("score") != null)
.mapToDouble(node -> node.map.get("score"))
.max()
.orElse(0.0);
Upvotes: 0
Reputation: 45329
You can compute the average values for each map key using:
Map<String, Double> result = Stream.of(m1, m2, m3)
.flatMap(m -> m.getMap1().entrySet().stream()
.filter(e -> e.getValue() != null))
.collect(Collectors.groupingBy(e -> e.getKey(),
Collectors.averagingDouble(e -> e.getValue())));
And the output for your test data is {score=60.0, rating=14.0, age=23.333333333333332}
Upvotes: 0
Reputation: 31968
You can get an average of age as:
Double averageAge = measurements.stream()
.flatMap(a -> a.getMetric().entrySet().stream())
.filter(a -> a.getKey().equals("age"))
.mapToDouble(Map.Entry::getValue)
.average()
.orElse(Double.NaN);
and similarly, averaging score would require an additional filter condition to exclude null
values.
Upvotes: 1