Продвинутые техники сортировки
В реальных приложениях нам часто требуется более сложная логика сортировки, например:
- Сортировка по нескольким критериям (например, сначала по среднему баллу (GPA), а если GPA равны, то по имени)
- Сортировка в обратном порядке
- Создание цепочек пользовательских компараторов (Comparator)
Рассмотрим эти продвинутые техники.
Сортировка по нескольким критериям
- Создайте новый файл с именем
MultiCriteriaDemo.java
в директории ~/project
:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MultiCriteriaDemo {
public static void main(String[] args) {
// Create a list of students with some having the same GPA
List<Student> students = new ArrayList<>();
students.add(new Student("John", 3.5, 101));
students.add(new Student("Mary", 3.8, 102));
students.add(new Student("Alice", 3.5, 103)); // Same GPA as John
students.add(new Student("Bob", 3.8, 104)); // Same GPA as Mary
students.add(new Student("Charlie", 3.2, 105));
// Print the unsorted list
System.out.println("Unsorted Student List:");
for (Student student : students) {
System.out.println(student);
}
// Sort first by GPA, then by name
Comparator<Student> byGpa = Comparator.comparing(Student::getGpa);
Comparator<Student> byName = Comparator.comparing(Student::getName);
// Combine the comparators using thenComparing
Comparator<Student> byGpaThenName = byGpa.thenComparing(byName);
// Sort the list
Collections.sort(students, byGpaThenName);
// Print the sorted list
System.out.println("\nStudents sorted by GPA, then by name:");
for (Student student : students) {
System.out.println(student);
}
}
}
Эта программа:
-
Создает список студентов, некоторые из которых имеют одинаковый средний балл (GPA)
-
Создает компаратор для GPA и компаратор для имени
-
Объединяет эти компараторы с помощью метода thenComparing()
-
Сортирует студентов сначала по GPA, а затем по имени, если GPA равны
-
Скомпилируйте и запустите код:
cd ~/project
javac Student.java MultiCriteriaDemo.java
java MultiCriteriaDemo
Вы должны увидеть вывод, похожий на следующий:
Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.5, Reg No: 103
Bob, GPA: 3.8, Reg No: 104
Charlie, GPA: 3.2, Reg No: 105
Students sorted by GPA, then by name:
Charlie, GPA: 3.2, Reg No: 105
Alice, GPA: 3.5, Reg No: 103
John, GPA: 3.5, Reg No: 101
Bob, GPA: 3.8, Reg No: 104
Mary, GPA: 3.8, Reg No: 102
Обратите внимание, что студенты с одинаковым GPA (Алиса и Джон с GPA 3.5, Боб и Мэри с GPA 3.8) отсортированы в алфавитном порядке.
Сортировка в обратном порядке
- Создайте новый файл с именем
ReverseOrderDemo.java
в директории ~/project
:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ReverseOrderDemo {
public static void main(String[] args) {
// Create a list of students
List<Student> students = new ArrayList<>();
students.add(new Student("John", 3.5, 101));
students.add(new Student("Mary", 3.8, 102));
students.add(new Student("Alice", 3.2, 103));
students.add(new Student("Bob", 3.9, 104));
students.add(new Student("Charlie", 3.0, 105));
// Print the unsorted list
System.out.println("Unsorted Student List:");
for (Student student : students) {
System.out.println(student);
}
// Method 1: Using Collections.reverseOrder() with a comparator
Comparator<Student> byGpa = Comparator.comparing(Student::getGpa);
Comparator<Student> byGpaReversed = Collections.reverseOrder(byGpa);
Collections.sort(students, byGpaReversed);
System.out.println("\nStudents sorted by GPA in descending order (Method 1):");
for (Student student : students) {
System.out.println(student);
}
// Method 2: Using the reversed() method of Comparator
Collections.sort(students, Comparator.comparing(Student::getName).reversed());
System.out.println("\nStudents sorted by name in reverse alphabetical order (Method 2):");
for (Student student : students) {
System.out.println(student);
}
}
}
Эта программа демонстрирует два способа сортировки в обратном порядке:
-
Использование Collections.reverseOrder()
для обращения компаратора
-
Использование метода reversed()
компаратора
-
Скомпилируйте и запустите код:
cd ~/project
javac Student.java ReverseOrderDemo.java
java ReverseOrderDemo
Вы должны увидеть вывод, похожий на следующий:
Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104
Charlie, GPA: 3.0, Reg No: 105
Students sorted by GPA in descending order (Method 1):
Bob, GPA: 3.9, Reg No: 104
Mary, GPA: 3.8, Reg No: 102
John, GPA: 3.5, Reg No: 101
Alice, GPA: 3.2, Reg No: 103
Charlie, GPA: 3.0, Reg No: 105
Students sorted by name in reverse alphabetical order (Method 2):
Mary, GPA: 3.8, Reg No: 102
John, GPA: 3.5, Reg No: 101
Charlie, GPA: 3.0, Reg No: 105
Bob, GPA: 3.9, Reg No: 104
Alice, GPA: 3.2, Reg No: 103
Первая сортировка показывает студентов в порядке убывания GPA, а вторая сортировка показывает студентов в обратном алфавитном порядке по имени.
Сложная цепочка сортировки
- Создадим еще один пример, который объединяет несколько критериев и обратную сортировку. Создайте файл с именем
ComplexSortingDemo.java
в директории ~/project
:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComplexSortingDemo {
public static void main(String[] args) {
// Create a list of students with varied data
List<Student> students = new ArrayList<>();
students.add(new Student("John", 3.5, 101));
students.add(new Student("Mary", 3.8, 102));
students.add(new Student("Alice", 3.5, 103)); // Same GPA as John
students.add(new Student("Bob", 3.8, 104)); // Same GPA as Mary
students.add(new Student("Charlie", 3.2, 105));
students.add(new Student("David", 3.2, 106)); // Same GPA as Charlie
// Print the unsorted list
System.out.println("Unsorted Student List:");
for (Student student : students) {
System.out.println(student);
}
// Create a complex sorting chain:
// 1. Sort by GPA in descending order
// 2. If GPAs are equal, sort by name in ascending order
// 3. If names are also equal, sort by registration number in descending order
Comparator<Student> complexComparator = Comparator
.comparing(Student::getGpa, Comparator.reverseOrder())
.thenComparing(Student::getName)
.thenComparing(Student::getRegNo, Comparator.reverseOrder());
Collections.sort(students, complexComparator);
System.out.println("\nStudents sorted by complex criteria:");
System.out.println("(GPA descending, then name ascending, then reg. number descending)");
for (Student student : students) {
System.out.println(student);
}
}
}
Эта программа создает сложную цепочку сортировки, которая:
-
Сначала сортирует студентов по GPA в порядке убывания
-
Если GPA равны, сортирует по имени в порядке возрастания
-
Если и GPA, и имя равны, сортирует по регистрационному номеру в порядке убывания
-
Скомпилируйте и запустите код:
cd ~/project
javac Student.java ComplexSortingDemo.java
java ComplexSortingDemo
Вы должны увидеть вывод, похожий на следующий:
Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.5, Reg No: 103
Bob, GPA: 3.8, Reg No: 104
Charlie, GPA: 3.2, Reg No: 105
David, GPA: 3.2, Reg No: 106
Students sorted by complex criteria:
(GPA descending, then name ascending, then reg. number descending)
Bob, GPA: 3.8, Reg No: 104
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.5, Reg No: 103
John, GPA: 3.5, Reg No: 101
Charlie, GPA: 3.2, Reg No: 105
David, GPA: 3.2, Reg No: 106
В этом выводе:
- У Боба и Мэри оба GPA равны 3.8, но Боб идет первым по алфавиту
- У Алисы и Джона оба GPA равны 3.5, но Алиса идет первой по алфавиту
- У Чарли и Дэвида оба GPA равны 3.2, и Чарли идет первым по алфавиту
Это демонстрирует, как можно создать сложную многоуровневую логику сортировки, объединяя компараторы в цепочку.