Как сделать сложную сортировку с помощью Comparable
Есть список содержащий ФИО,оценку по русскому,оценку по математике,оценку по физике. Мне нужно отсортировать студентов от лучшего к худшему по 3 критериям: максимальная сумма баллов, затем с большим баллом по математике, затем по физике(сначала проверяет по сумме баллов, если будут одинаковые суммы , то уже проверяет баллы по математике, а если по математике одинаковые оценки , то проверяет по физике) Например:
List<Student> list = new ArrayList<Student>();
list.add((new Student("Сергуй","Сергуй","Сергуй",3,5,2))); //1 оценка-русский,2-математика,3-физ
list.add((new Student("Кирилл","Кирилл","Кирилл",4,2,4)));
list.add((new Student("Дмитрий","Дмитрий","Дмитрий",5,4,3)));
list.add((new Student("Саня","Саня","Саня",2,3,5)));
Должно получиться : Дмитрий, Сергуй, Саня, Кирилл
Есть класс student для описания каждого из студентов:
public class Student implements Comparable<Student>{
String SecondName;
String FirstName;
String Othestvo;
int RussianMark;
int MathMark;
int PhysicMark;
int TotalMark;
public Student(String SecondName, String FirstName, String Othestvo, int RussianMark, int MathMark, int PhysicMark) {
this.SecondName = SecondName;
this.FirstName = FirstName;
this.Othestvo = Othestvo;
this.RussianMark = RussianMark;
this.MathMark = MathMark;
this.PhysicMark = PhysicMark;
}
public String getSecondName() {
return SecondName;
}
public void setSecondName(String secondName) {
SecondName = secondName;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getOthestvo() {
return Othestvo;
}
public void setOthestvo(String othestvo) {
Othestvo = othestvo;
}
public int getRussianMark() {
return RussianMark;
}
public void setRussianMark(int russianMark) {
RussianMark = russianMark;
}
public int getMathMark() {
return MathMark;
}
public void setMathMark(int mathMark) {
MathMark = mathMark;
}
public int getPhysicMark() {
return PhysicMark;
}
public void setPhysicMark(int physicMark) {
PhysicMark = physicMark;
}
public int getTotalMark() {
return RussianMark + MathMark + PhysicMark;
}
public void setTotalMark(int totalMark) {
TotalMark = totalMark;
}
@Override
public int compareTo(Student student) {
if(MathMark == student.getMathMark()){
return 0;
}
if(MathMark < student.getMathMark()){
return 1;
}
return -1;
}
}
У меня получилось сделать сортировку по математике(см последние строчки в классе).Но сделать сортировку с учетом всех критериев не получается, буду рад если поможете.
Ответы (3 шт):
Можно сделать интегральную оценку как взвешенную сумму произведений баллов, по которой и производить сравнение. Веса соответствуют значимости оценок, например, "всего" умножаем на 100, математику на 10, физику на 1:
@Override
public int compareTo(Student student) {
return Integer.compare(student.getTotalMark() * 100 + student.getMathMark() * 10 + student.getPhysicMark(), getTotalMark() * 100 + getMathMark() * 10 + getPhysicMark());
}
@Override
public String toString() {
return getSecondName() + ": " + getTotalMark() + ", " + getMathMark() + ", " + getPhysicMark();
}
После сортировки
list.sort(Student::compareTo);
[Дмитрий: 12, 4, 3, Сергуй: 10, 5, 2, Саня: 10, 3, 5, Кирилл: 10, 2, 4]
Можете использовать методы интерфейса Comparator для более удобного описания условия сравнения объектов
@Override
public int compareTo(Student student) {
return Comparator.comparing(Student::getTotalMark)
.thenComparing(Student::getMathMark)
.thenComparing(Student::getPhysicMark)
.reversed()
.compare(this, student);
}
Похожая конструкция также используется для определения алгоритма сравнения (например в методах Collections.sort(List list, Comparator c), List.sort(Comparator c)), если класс не реализует интерфейс Comparable либо логика приложения подразумевает несколько вариантов алгоритмов сравнения.
Чтобы реализовать логику сравнения, воспользуйтесь статическим методом Integer.compare сравнения двух чисел:
@Override
public int compareTo(Student other) {
int c1 = Integer.compare(other.getTotalMark(), this.getTotalMark());
if (c1 != 0) return c1;
int c2 = Integer.compare(other.getMathMark(), this.getMathMark());
if (c2 != 0) return c2;
return Integer.compare(other.getPhysicMark(), this.getPhysicMark());
}
Отсортировать список можно с помощью Collections.sort:
Collections.sort(list);