Search code examples
javajava-8java-streamcode-snippets

Get maximum of average subject marks using java 8 stream


I have class student as below

 class Student{
        Map<String,Integer> subjectMarks;
        String name;
        
        
        public Student(Map<String,Integer> subject, String name) {
            super();
            this.subjectMarks = subject;
            this.name = name;
        }
        public Map<String,Integer> getSubjectMarks() {
            return subjectMarks;
        }
        public void setSubjectMarks(Map<String,Integer> subject) {
            this.subjectMarks = subject;
        }
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
     }

In main method we add student object in arraylist as follow.

        ArrayList<Student> arr = new ArrayList<Student>();
        Map m1 = new HashedMap();
        m1.put("Maths",40);
        m1.put("Science",50);
        Map m2 = new HashedMap();
        m2.put("Maths",60);
        m2.put("Science",20);
        arr.add(new Student(m1, "RAJ"));
        arr.add(new Student(m2, "AMIT"));

can some help/guide me to find average marks of subject for each student and then get maximum from averge. I want help to write this snippet in java8


Solution

  • Do not limit yourself to the idea of streams in Java 8 where you have to process a stream result directly into the next stream and so on... The efficiency might not be the best but consider to nest loops.

    Start to think what you have: several marks for every Student. You want to find the average of these marks for every Student. You can reduce the problem to first think on how to get the average for one Student.

    double average = student.getSubjectMarks().values().stream()
            .mapToInt(Integer::valueOf).average().orElse(0.0);
    

    Even though your examples show only integer numbers, averages can also be floating point numbers.

    Then, you would have to loop through all students and execute the procedure above for every student.

    Map<String, Double> studentAverages = new HashMap<>();
    
    arr.forEach(student -> {
        double average = student.getSubjectMarks().values().stream()
                .mapToInt(Integer::valueOf).average().orElse(0.0);
        studentAverages.put(student.getName(), average);
    });
    

    In the described implementation, the required averages are saved in the Map studentAverages which has the names of the students as a key and the average mark as a value.

    You can then simply get the maximum integer from your list.

    studentAverages.values().stream().mapToDouble(Double::doubleValue).max();
    

    Some answers provide more sophisticated usages of streams. However, the code above is more readable. Furthermore, the data type Object is very general, difficult for further usage and error prone.