2

So I have a Student class, and I have to get the best and scores from the students, but it's all grouped by their courseid. Basically I have to get the best and worst score in each specific course. Everything is taken from a file students.txt and this is my code so far.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class Main
{
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("src/students.txt");
        List<String> lines = Files.readAllLines(path);
        ArrayList<Student> students = new ArrayList<>();
        for (String line:lines) {
            String[] rawlines = line.split(",");
            String name  = rawlines[0];
            String lname  = rawlines[1];
            String courseID  = rawlines[2];
            String score = rawlines[3];
            double doublescore = Double.parseDouble(score);

            Student student = new Student(name, lname, courseID, doublescore);
            students.add(student);
        }

        for (Student s : students) {
            System.out.println(s);
        }
    }
}

Also I need to use threads to make this parallel, but that's not my main concern right now. The lines in the file are set up like this: Joe, Doe, CS280, 92

bmargulies
  • 97,814
  • 39
  • 186
  • 310
Zijah
  • 31
  • 3
  • Do you mean you need to only get the worst and the best results in each couse, or you mean you kind of need to sort your Student list by course id, then by grades? – Sirmyself Jan 25 '18 at 19:41
  • There is no [tag:serializaion] here. Don't tag indiscriminately. – user207421 Jan 26 '18 at 00:10

2 Answers2

2

You can use Collectors.groupingBy and Collectors.summarizingDouble to get a DoubleSummaryStatistics which includes min, max, avg, etc. Example:

Having:

class Student{
    private String name;
    private String lname;
    private String courseID;
    private double score;
    // getters 'n setters, constructors, toString, etc
}

and

List<Student> students = new ArrayList<>(Arrays.asList(
    new Student("student1", "student1", "course1", 90),
    new Student("student2", "student2", "course2", 86),
    new Student("student3", "student3", "course3", 92),
    new Student("student4", "student4", "course1", 80),
    new Student("student5", "student5", "course2", 93),
    new Student("student6", "student6", "course3", 78),
    new Student("student7", "student7", "course1", 95),
    new Student("student8", "student8", "course2", 83),
    new Student("student9", "student9", "course3", 79),
    new Student("student10", "student10.", "course1", 88)
));

You can do this:

Map<String, DoubleSummaryStatistics> statistics = students.stream()
        .collect(Collectors.groupingBy(Student::getCourseID,
                                       Collectors.summarizingDouble(Student::getScore)));

Output:

course3=DoubleSummaryStatistics{count=3, sum=249.000000, min=78.000000, average=83.000000, max=92.000000}, 
course2=DoubleSummaryStatistics{count=3, sum=262.000000, min=83.000000, average=87.333333, max=93.000000}, 
course1=DoubleSummaryStatistics{count=4, sum=353.000000, min=80.000000, average=88.250000, max=95.000000}

Here we have a list of students. We group the students by courseId and then get the statistics in each course based on the scores. Then we can get the values of each course like:

statistics.get("course1").getMin();
statistics.get("course2").getMax();

If there are performance concerns about this proccess and you want it parallel, you can use a parallelStream instead:

Map<String, DoubleSummaryStatistics> statistics = students.parallelStream()
        .collect(Collectors.groupingBy(Student::getCourseID,
Juan Carlos Mendoza
  • 5,736
  • 7
  • 25
  • 50
1

I'd approach it like this:

Create a class to encapsulate your best and worst score, something like:

class CourseStat{
    private double bestScore;
    private double worstScore;

constructor ...gettersandsetters...
}

Then create a HashMap where the key is the courseID. Basically something like:

HashMap<String,CourseStat> courseMap = new HashMap<>();
for (Student s : students) {
    if(courseMap.contains(s.getCourseId())){
        CourseStat stat = courseMap.get(s.getCourseId());
        //Set the maximum and minimum score of the stat comparing the worst and best score with the current student.
        //...code goes here ...
    }
    else{
        //Create the course, add it to the map and set worst and best score to the current student's score.
        courseMap.put(s.getCourseId(),new CourseStat(s.getScore(),s.getScore()));
    }
}

Then you will have a hashmap , indexed by the course Id and an object representing the worst and best score for your students.

arocketman
  • 1,134
  • 12
  • 21