I have List<MyObjects>
with 4 fields:
String fieldText;
double fieldDoubleOne;
double fieldDoubleTwo;
double fieldDoubleThree;
What would be the best (Java-8) way of collecting and printing out the list, sorted according to Average(fieldDoubleOne) so that the console output looks something like: fieldText → Average(fieldDoubleOne) → Average(fieldDoubleTwo) → Average(fieldDoubleThree) Assume public getters for all fields. For one double field, I had, from my previous question :
Map<String, List<MyObject>> groupByFieldText = myObjectList.stream().collect(groupingBy(MyObject::getFieldText));
Map<String, Double> averageMap = groupByFieldText.entrySet().stream()
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey(),
e.getValue().stream()
.mapToDouble(d -> d.getDoubleOne()).average()
.orElse(0d)))
.sorted(Comparator.comparingDouble(Map.Entry::getValue))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(v1, v2) -> v1, LinkedHashMap::new));
averageMap.entrySet().stream().sorted(Comparator.comparingDouble((Map.Entry::getValue)))
.forEach(System.out::println);
You just need to sort the entries instead of mapping their value to double
, like that:
Map<String, List<MyObject>> sortedByAverageOne = groupByFieldText.entrySet().stream()
.sorted(Comparator.comparingDouble(e -> average(e, MyObject::getDoubleOne)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(v1, v2) -> v1, LinkedHashMap::new));
Note that if you have a lot of entries, it won't be very efficient because it calls average
for every comparison.
Then, having such a sorted map you print it as follows:
sortedByAverageOne.entrySet().stream()
.map(e -> String.format(
"%s → %f → %f → %f",
e.getKey(),
average(e, MyObject::getDoubleOne),
average(e, MyObject::getDoubleTwo),
average(e, MyObject::getDoubleThree)
))
.forEach(System.out::println);
Finally, average
is defined as:
private static double average(Map.Entry<String, List<MyObject>> entry, ToDoubleFunction<MyObject> getter) {
return average(entry.getValue(), getter);
}
private static double average(List<MyObject> list, ToDoubleFunction<MyObject> getter) {
return list.stream().mapToDouble(getter).average().orElse(0);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.