#java #java-stream
#java #java-поток
Вопрос:
Я совершенно новичок, поэтому прошу вас не ругаться слишком сильно)
Существует коллекция (ArrayList), в которой хранятся объекты класса Student (<HashMap <Тема, целое число> рейтинг, имя строки>). Я должен рассчитать средний балл по конкретному предмету, используя Stream API. Я пытался сделать это следующим образом:
sumOnSubjectInGroup = studentsInGroup.stream()
.filter(e -> e.getRating().entrySet().iterator().next().getKey().equals(subject))
.mapToInt(e -> e.getRating().entrySet().iterator().next().getValue())
.reduce(0, (x, y) -> x y);
countMarkInGroup = (int) studentsInGroup.stream()
.filter(e -> e.getRating().entrySet().iterator().next().getKey().equals(subject))
.count();
return (double) sumOnSubjectInGroup / countMarkInGroup;
где
sumOnSubjectInGroup — это сумма баллов по предметам всех учащихся.
countMarkInGroup — количество таких меток.
studentsInGroup — это коллекция со всеми объектами Student.
getRating () — возвращает HashMap <Subject, Integer> со списком элементов и рейтингами для него.
Но, очевидно, я получил неправильный результат
Ответ №1:
Вы можете использовать .average()
для вычисления среднего значения и использовать containsKey
для проверки наличия на карте для фильтрации и получения оценки.
Double average = studentsInGroup.stream()
.filter(e -> e.getRating().containsKey(subject))
.mapToInt(e -> e.getRating().get(subject))
.average()
.orElse(0.0);
Комментарии:
1. Но по какой-то причине это не работает с более сложной структурой. ArrayList — Arraylist — Student (<Хэш-карта <Тема, целое число> рейтинг, имя строки>). prnt.sc/u7pck4 Я получаю неверный результат.
2. @robert0801 Вам нужно
flatMap
вместоmap
ArrayList<Student>
сгладить вStudent
подобие.flatMap(g -> g.getStudentsInGroup.stream())
Ответ №2:
Вы можете использовать Collectors.averagingInt
для вычисления среднего значения без отдельного вычисления суммы и подсчета по субъекту.
import java.util.*;
import java.util.stream.*;
class Student {
String name;
Map<String, Integer> rating;
public Student(String name, Map<String, Integer> grades) {
this.name = name;
this.rating = grades;
}
public String getName() { return name; }
public Map<String, Integer> getRating() { return rating; }
}
public class Main {
public static void main(String args[]) {
List<Student> students = Arrays.asList(
new Student("John", Map.of("Math", 90, "Physics", 94, "Chemistry", 93, "English", 92)),
new Student("Jack", Map.of("Math", 73, "Physics", 76, "English", 89)),
new Student("Jane", Map.of("Math", 87, "Chemistry", 91, "French", 94)),
new Student("Joel", Map.of("Math", 81, "Physics", 79, "French", 88))
);
students
.stream()
.flatMap(s -> s.getRating().entrySet().stream())
.collect(Collectors.groupingBy(
Map.Entry::getKey, Collectors.averagingInt(Map.Entry::getValue)))
.entrySet()
.forEach(System.out::println);
}
}
Вывод:
English=90.5
Chemistry=92.0
French=91.0
Math=82.75
Physics=83.0