0
votes

i have an array of students, these students have an map of subjects and points earned as Double.

I am very new to streams, and programming in general, so not sure other ways to go about this problem as researching streams dont give me a clear answer.

running on Java 11

Appreciate the help, and would prefer simple explanations or resources so i can understand it as simple as possible

What i am trying to do: Calculate the average score of all the students in a specific subject with the help of Java Streams.

What i did:

allStudentsArray.stream().mapToDouble(s -> s.examPoints.get("Math")).average().getAsDouble();

This only throws me error: Exception in thread "main" java.lang.NullPointerException at Main.lambda$main$0(Main.java:39) at java.base/java.util.stream.ReferencePipeline$6$1.accept(ReferencePipeline.java:246) at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.DoublePipeline.collect(DoublePipeline.java:514) at java.base/java.util.stream.DoublePipeline.average(DoublePipeline.java:467) at Main.main(Main.java:39)

codebase:

public class Student {

    public int student_id;
    public String name;
    Map<String, Double> examPoints = new HashMap<String, Double>();

    public Student(int student_id, String name) {
        this.student_id = student_id;
        this.name = name;
    }

    public void setExamPoints(String name, Double points){

        examPoints.put(name, points);


    }
}

Main:

Student studentOne = new Student(1, "Ole");
        studentOne.setExamPoints("Programmering", 20.0);
        studentOne.setExamPoints("Math", 10.0);
        studentOne.setExamPoints("Algdat", 25.5);


        Student studentTwo = new Student(2, "Åge");
        studentTwo.setExamPoints("Fysikk", 12.0);
        studentTwo.setExamPoints("Math", 15.0);
        studentTwo.setExamPoints("Algdat", 65.5);

        Student studentThree = new Student(3, "Per");
        studentThree.setExamPoints("Matte", 24.2);
        studentThree.setExamPoints("Gym", 45.0);
        studentThree.setExamPoints("Algdat", 29.3);

        Student studentFour = new Student(4, "Svein");
        studentFour.setExamPoints("Programmering", 90.0);
        studentFour.setExamPoints("AdvJava", 99.0);
        studentFour.setExamPoints("Science", 29.5);

        ArrayList<Student> allStudents = new ArrayList<Student>();
        allStudents.add(studentOne);
        allStudents.add(studentTwo);
        allStudents.add(studentThree);
        allStudents.add(studentFour);


       allStudents.stream().mapToDouble(s -> s.examPoints.get("Algdat")).average().getAsDouble();
1
I would recommend you to debug your application and to use peek for sole purpose to debug your streams - Pawan.Java
Not everyone of your Student objects has a Map entry for the key "Algdat" so s.examPoints.get("Algdat") will return null for your 4th student. You can either first filter your stream to only include those that have this key in their ExamPoints map, or you use a map function that returns a default value if the key isn't found instead of the standard get method. - OH GOD SPIDERS
studentFour has no entry for "Algdat". - f1sh
oh, so i would first filter all the students to remove the ones that dont have algdat, then i would do mapToDouble(s -> s.examPoints.get("Algdat")).average().getAsDouble(); on the result of that instead, that makes more sense - catfish
like @f1sh mentioned. so you are trying to get an average on an array with a null value and getting a NullPointerException. Add "Algdat" to StudentThree or use a condition in .mapToDouble like if(!s.examPoints.get("Algdat")) { return 0;} else {return s.examPoints.get("Algdat")) - Johannes Griebenow

1 Answers

1
votes

Filter first:

double asDouble = allStudents.stream()
.filter(s -> s.examPoints.containsKey("Algdat"))
.mapToDouble(s -> s.examPoints.get("Algdat"))
.average()
.getAsDouble();