Java Сортировка объектов с несколькими параметрами

89
8

Недавно я работал над улучшением понимания алгоритмов сортировки и их отношения к различным типам ввода. В настоящее время я работаю над программой управления студентами, где каждый студент имеет три параметра: Фамилия, ГПД и ИД пользователя (String, double, int). Каждый из них хранится в классе Student с этими тремя параметрами, и есть ДОЗЫ студентов (ключевая особенность программы заключается в том, чтобы вводить, удалять и обновлять учащихся).


Мой вопрос: используя основные алгоритмы сортировки (mergesort, quicksort и т.д.), каков наилучший способ сортировки моего списка студентов по каждому параметру? Например, каков наилучший способ выполнить объединение, чтобы отсортировать список по GPA? Или использовать quicksort для сортировки списка по фамилии?


В сущности, мой вопрос сводится к... Я могу сортировать эти объекты, если у них не было трех параметров (для меня очень легко написать слияние для сортировки 100 номеров). Как мне управлять двумя другими параметрами и убедиться, что они доступны после сортировки?

спросил(а) 2021-01-19T18:32:47+03:00 6 месяцев, 1 неделя назад
1
Решение
110

Как это делается на Java, нужно использовать разные Компараторы. Затем вы говорите:


Collections.sort(list, new NameComparator());

или


Collections.sort(list, new GpaComparator());

Эти компараторы используют разные поля для определения порядка между двумя элементами.

Например, Компаратор имени может быть:


class NameComparator implements Comparator< Student> {
@Override public int compare(Student left, Student right) {
return left.getName().compareTo(right.getName());
}
}

И GpaComparator может быть


class GpaComparator implements Comparator< Student> {
@Override public int compare(Student left, Student right) {
if (left.getGpa() < right.getGpa()) {
return -1;
} else if (left.getGpa() > right.getGpa()) {
return 1;
} else {
return 0;
}
}

ответил(а) 2021-01-19T18:32:47+03:00 6 месяцев, 1 неделя назад
65

Я бы рекомендовал реализовать интерфейс Comparable в вашем Student классе, как этот


public class Student implements Comparable {
public int compareType; //you can make this an enum if you want
...

public int compareTo(Object o) {
if(compareType == 0)
return gpaCompareTo(o);
else if(compareType == 1)
return nameCompareTo(o);

return idCompateTo(o);
}

public int gpaCompareTo(Object o) {
//implement your gpaCompareTo
}

public int nameCompareTo(Object o) {
//implement your nameCompareTo
}

public int idCompareTo(Object o) {
//implement your idCompareTo
}
}


И затем используйте встроенный вид, например


List<Student> list = new ArrayList<Student>();
...
Collections.sort(list);

Или вы не можете реализовать Comparable и создать свои собственные компараторы


public class MyComparator implements Comparator<Student> {

public int compare(Student o1, Student o2) {
//implement the comparator
}

public boolean equals(Object o) {
//implement the equals
}
}


Затем вы можете использовать другой метод сортировки Collection's


Collections.sort(list, MyComparator);

ответил(а) 2021-01-19T18:32:47+03:00 6 месяцев, 1 неделя назад
64

Это, вероятно, не в тему, но если вы хотите попробовать что-то классное, JDK 8 Lambda Preview предлагает несколько классных способов определить компараторы используя выражения Lamda и ссылки на методы.


Скажем, у нас есть класс:


class Jedi  {
private final String name;
private final int age;
//...
}

И затем их набор:


List<Jedi> jediAcademy = asList(new Jedi("Obiwan",80), new Jedi("Anakin", 30));
sort(jediAcademy, (j1, j2) -> j1.getAge() > j2.getAge() ? 1 : j1.getAge() < j2.getAge() ? -1 : 0);
System.out.println(jediAcademy); //Anakin, Obiwan

Или с ссылками на методы, если у Jedi есть метод, который ведет себя как компаратор (та же подпись)


class Jedi  {
public static int compareByAge(Jedi first, Jedi second){
return first.age > second.age ? 1 : first.age < second.age ? -1 : 0;
}
//...
}

Что можно использовать следующим образом для создания компаратора с помощью ссылки на метод:


List<Jedi> jediAcademy = asList(new Jedi("Obiwan",80), new Jedi("Anakin", 30));
sort(jediAcademy, Jedi::compareByAge);
System.out.println(jediAcademy);//Anakin, Obiwan

ответил(а) 2021-01-19T18:32:47+03:00 6 месяцев, 1 неделя назад
64

Типичный способ сделать это - написать общий алгоритм сортировки для любого типа, который принимает Comparator, а затем писать разные Comparator для сортировки по разным полям.

ответил(а) 2021-01-19T18:32:47+03:00 6 месяцев, 1 неделя назад
45

Это действительно не что иное, как сортировка чисел, за исключением того, что в этом случае ваши "цифры" являются тремя полями ваших пользователей, значение каждой цифры ограничено значениями каждого поля, а порядок полей определяет сортировка.


Чтобы быть более конкретным, у вас есть Tupple с тремя полями: <GPA, Last Name, User ID> и позволяет предположить, что вы хотите сортировать по GPA, а затем по Фамилии и идентификатора пользователя.


Точно так же, как 219 сортируется выше 139 (т.е. цифра "сотни" имеет более высокое значение, даже если цифра "десятки" ниже), табло, подобное <3.75, Jones, 5>, будет отсортировано выше <3.0, Adams, 2>, потому что "цифра GPA" (что более значительна) имеет более высокое значение, даже если "фамильная цифра" ниже (например, Jones "ниже", чем Adams).

ответил(а) 2021-01-19T18:32:47+03:00 6 месяцев, 1 неделя назад
45

Использовать несколько компараторов


class Student
{

String lastName;
dounle GPA;
int userId

static Comparator<Student> getStudentLastNameComparator() {
return new Comparator<Student>() {

@Override
public int compare(Student Student1, Student Student2) {
return Student1.getlastName().compareTo(Student2.getlastName());
}
// compare using Student lastName
};
}

static Comparator<Student> getStudentGPAComparator() {
return new Comparator<Student>() {

@Override
public int compare(Student Student1, Student Student2) {
if(Student1.GPA < Student2.GPA)
return 1;
else
return -1;
}
// compare using Student GPA
};
}

static Comparator<Student> getStudentUserIdComparator() {
return new Comparator<Student>() {

@Override
public int compare(Student Student1, Student Student2) {
if(Student1.userId < Student2.userId)
return 1;
else
return -1;
}
// compare using Student userId
};
}
}

ответил(а) 2021-01-19T18:32:47+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема