Вычислить сумму значений на карте из Stream Api

#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