简体   繁体   中英

Sorting values from ArrayList inside HashMap

I'm having a hard time trying to solve my problem. I have to sort students in descending order by highest average mark and also to show the average mark of all students. I will include my Main class and declarations from my other classes.

public Main()
{
    ArrayList<Student> students = new ArrayList<Student>();
    Student A = new Student("John", "Doe", 1000);
    students.add(A);
    Student B = new Student("Michael", "Hawk", 2000);
    students.add(B);
    Student C = new Student("Nicholas", "Johnson", 3000);
    students.add(C);

    HashMap<Integer, ArrayList<PassedExams>> map = new HashMap<Integer, ArrayList<PassedExams>>();

    for (Student student : students)
    {
        map.put(student.getIndeks(), new ArrayList<PassedExams>());
    }

    for (Entry<Integer,ArrayList<PassedExams>> exam : map.entrySet())
    {
        if (exam.getKey() == 1000)
        {
            ArrayList<PassedExams> passedExam = exam.getValue();
            passedExam.add(new PassedExams("CS102", 6));
            passedExam.add(new PassedExams("CS220", 8));
            exam.setValue(passedExam);
        }
        if (exam.getKey() == 2000)
        {
            ArrayList<PassedExams> passedExam = exam.getValue();
            passedExam.add(new PassedExams("MA101", 10));
            passedExam.add(new PassedExams("CS101", 7));
            exam.setValue(passedExam);
        }
        if (exam.getKey() == 3000)
        {
            ArrayList<PassedExams> passedExam = exam.getValue();
            passedExam.add(new PassedExams("CS115", 9));
            passedExam.add(new PassedExams("MA102", 7));
            exam.setValue(passedExam);
        }
    }

    for (Student student : students)
    {
        System.out.println(student.toString() + " " + map.get(student.getIndex()));
    }
}

`

public class PassedExams
{
    private String code;
    private Integer mark;
    // get and set methods
    // aswell as toString();
}

`

public class Student
{
    private String name, surname;
    private Integer index;
    // get and set methods
    // aswell as toString();
}

EDIT: Adding input and output

What is seen by default:

Student Name: John Surname: Doe Index: 1000 [Predmet:  Code: CS102 Mark: 6, Predmet:  Code: CS220 Mark: 8]
Student Name: Michael Surname: Hawk Index: 2000 [Predmet:  Code: MA101 Mark: 10, Predmet:  Code: CS101 Mark: 7]
Student Name: Nicholas Surname: Johnson Index: 3000 [Predmet:  Code: CS115 Mark: 9, Predmet:  Code: MA102 Mark: 7]

What should be seen after sort:

Student Name: Michael Surname: Hawk Index: 2000 [Predmet:  Code: MA101 Mark: 10, Predmet:  Code: CS101 Mark: 7]
Student Name: Nicholas Surname: Johnson Index: 3000 [Predmet:  Code: CS115 Mark: 9, Predmet:  Code: MA102 Mark: 7]
Student Name: John Surname: Doe Index: 1000 [Predmet:  Code: CS102 Mark: 6, Predmet:  Code: CS220 Mark: 8]

And total average mark :

Total average mark from students is: 7.83

Also I guess I should change from Integer to Double because of the line above.

Draken is right, it's more elegant to model the passed exams list as property of a student. However, you can sort your students with the way things are. When you want to define an order on a list in Java you can write a special Comparator:

    //sorting starts here
    Collections.sort(students, new Comparator<Student>() {
        @Override
        public int compare(Student o1, Student o2) {
            double sum1 = 0, sum2 = 0;

            for (PassedExams pe : map.get(o1.getIndex())) sum1+=pe.mark;
            for (PassedExams pe : map.get(o2.getIndex())) sum2+=pe.mark;

            sum1 /= map.get(o1.getIndex()).size();
            sum2 /= map.get(o2.getIndex()).size();

            return Double.compare(sum2, sum1);
        }
    });

I don't think you need a hashMap First add all students in the list.
Implement a Comparator, the comparator would probably have a method: getExamsForStudent()
Then sort the list using Collections.sort(list, comparator).

Here's the elegant way to do it (I'm using Java 1.7, so please ignore the lack of predicates!)

Main

public class App {

    public static void main(String[] args) {
        new App();
    }
    public App()
    {
        ArrayList<Student> students = new ArrayList<Student>();
        Student A = new Student("John", "Doe", 1000);
        students.add(A);
        Student B = new Student("Michael", "Hawk", 2000);
        students.add(B);
        Student C = new Student("Nicholas", "Johnson", 3000);
        students.add(C);

        for (Student student : students)
        {
            if (student.getIndex() == 1000)
            {
                student.getPassedExamList().add(new PassedExam("CS102", 6));
                student.getPassedExamList().add(new PassedExam("CS220", 8));
            }
            if (student.getIndex() == 2000)
            {
                student.getPassedExamList().add(new PassedExam("MA101", 10));
                student.getPassedExamList().add(new PassedExam("CS101", 7));
            }
            if (student.getIndex() == 3000)
            {
                student.getPassedExamList().add(new PassedExam("CS115", 9));
                student.getPassedExamList().add(new PassedExam("MA102", 7));
            }
        }
        for (Student student : students)
        {
            System.out.println(student.toString() + " " + student.getPassedExamList());
        }
        Collections.sort(students);
        System.out.println("\nSorted\n");
        for (Student student : students)
        {
            System.out.println(student.toString() + " " + student.getPassedExamList());
        }

        System.out.println("\nCalculating average\n");
        double total = 0;
        double count = 0;
        for (Student student : students)
        {
            count += student.getPassedExamList().size();
            total += student.getTotalMarks();
        }
        DecimalFormat df = new DecimalFormat("0.##");
        System.out.println("Average is " + df.format(total / count));
    }
}

Passed exam

public class PassedExam {
    private String code;
    private Integer mark;

    public PassedExam(String code, int mark){
        this.code = code;
        this.mark = mark;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public Integer getMark() {
        return mark;
    }

    public void setMark(Integer mark) {
        this.mark = mark;
    }

    @Override
    public String toString() {
        return "PassedExams{" +
                "code='" + code + '\'' +
                ", mark=" + mark +
                '}';
    }

}

Student

public class Student implements Comparator<Student>, Comparable<Student> {
    private String name, surname;
    private Integer index;
    private List<PassedExam> passedExamList = new ArrayList<PassedExam>();

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public Integer getIndex() {
        return index;
    }

    public void setIndex(Integer index) {
        this.index = index;
    }

    public List<PassedExam> getPassedExamList() {
        return passedExamList;
    }

    public int getTotalMarks(){
        int total = 0;
        for(PassedExam exam : passedExamList)
            total += exam.getMark();
        return total;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", surname='" + surname + '\'' +
                '}';
    }

    @Override
    public int compare(Student o1, Student o2) {
        return Integer.compare(o2.getTotalMarks(), o1.getTotalMarks());
    }

    @Override
    public int compareTo(Student o) {
        return Integer.compare(o.getTotalMarks(), this.getTotalMarks());
    }
}

The thing that allows me to call Collections.sort() is the fact that I implement Comparable<Student> on the Student class. I then add the method compareTo() and state how I want it sorting. Since you wanted descending order, I've reverse the normal order of comparison. You can read more on Comparable here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM