Comparator и Comparable

JavaJavaBeginner

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В Java-приложениях мы часто должны сравнивать и сортировать объекты. Для примитивных типов данных, таких как целые числа или строки, Java уже знает, как их сравнивать. Однако для пользовательских объектов нам нужно указать Java, как их сравнивать и упорядочивать.

Java предоставляет два интерфейса для решения этой задачи:

  • Интерфейс Comparable позволяет классу определить свою естественную упорядоченность.
  • Интерфейс Comparator предоставляет внешнюю логику сравнения, которая может использоваться для различных критериев сортировки.

В этом практическом занятии (LabEx) вы научитесь реализовывать оба интерфейса и использовать их для сортировки коллекций объектов различными способами.

Понимание интерфейса Comparable

Интерфейс Comparable используется, когда класс имеет естественную упорядоченность. Например, строки естественным образом упорядочиваются по алфавиту, а целые числа — по значению.

Когда класс реализует интерфейс Comparable, он должен определить метод compareTo(), который указывает, как должны быть упорядочены экземпляры этого класса.

Создание базового класса Student

Создадим простой класс Student, чтобы показать, как использовать интерфейс Comparable. Определим студента с именем, средним баллом (GPA) и регистрационным номером.

  1. Откройте WebIDE и создайте новый файл с именем Student.java в директории ~/project со следующим кодом:
public class Student implements Comparable<Student> {
    private String name;
    private double gpa;
    private int regNo;

    public Student(String name, double gpa, int regNo) {
        this.name = name;
        this.gpa = gpa;
        this.regNo = regNo;
    }

    // Implementing the compareTo method from Comparable interface
    @Override
    public int compareTo(Student other) {
        // Compare students based on GPA
        if (this.gpa < other.gpa) {
            return -1;
        } else if (this.gpa > other.gpa) {
            return 1;
        } else {
            return 0;
        }
    }

    // Getters
    public String getName() {
        return name;
    }

    public double getGpa() {
        return gpa;
    }

    public int getRegNo() {
        return regNo;
    }

    @Override
    public String toString() {
        return name + ", GPA: " + gpa + ", Reg No: " + regNo;
    }
}

Разберём этот код:

  • Класс Student реализует интерфейс Comparable<Student>
  • Метод compareTo() сравнивает студентов по их среднему баллу (GPA)
  • Если средний балл текущего студента меньше, чем у другого студента, возвращаем -1
  • Если средний балл текущего студента больше, чем у другого студента, возвращаем 1
  • Если средние баллы равны, возвращаем 0

Теперь создадим простую тестовую программу, чтобы увидеть, как можно использовать интерфейс Comparable для сортировки студентов.

  1. Создайте новый файл с именем ComparableDemo.java в директории ~/project со следующим кодом:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparableDemo {
    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));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort the list using the natural ordering (defined by compareTo method)
        Collections.sort(students);

        // Print the sorted list
        System.out.println("\nStudents sorted by GPA (using Comparable):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

Эта программа:

  1. Создаёт список объектов Student

  2. Выводит несортированный список

  3. Сортирует список с помощью метода Collections.sort(), который использует естественную упорядоченность, определённую методом compareTo()

  4. Выводит отсортированный список

  5. Теперь скомпилируем и запустим наш код, чтобы увидеть результат:

cd ~/project
javac Student.java ComparableDemo.java
java ComparableDemo

Вы должны увидеть вывод, похожий на следующий:

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

Students sorted by GPA (using Comparable):
Alice, GPA: 3.2, Reg No: 103
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Bob, GPA: 3.9, Reg No: 104

Как вы можете видеть, студенты теперь отсортированы по их среднему баллу (GPA) в порядке возрастания. Это естественная упорядоченность, которую мы определили в методе compareTo().

Создание и использование компараторов (Comparator)

В то время как интерфейс Comparable определяет естественную упорядоченность для класса, иногда нам нужно сортировать объекты по разным критериям. Именно здесь приходит на помощь интерфейс Comparator.

Интерфейс Comparator позволяет нам определить пользовательскую логику упорядочивания, которая отделена от класса, объекты которого сравниваются. Это означает, что мы можем иметь несколько способов сортировки объектов одного и того же класса.

Создание компаратора для сортировки по имени

Создадим Comparator, который сортирует студентов по их именам в алфавитном порядке:

  1. Создайте новый файл с именем StudentNameComparator.java в директории ~/project со следующим кодом:
import java.util.Comparator;

public class StudentNameComparator implements Comparator<Student> {
    @Override
    public int compare(Student s1, Student s2) {
        // Compare students based on their names
        return s1.getName().compareTo(s2.getName());
    }
}

Этот Comparator:

  • Реализует интерфейс Comparator<Student>
  • Определяет метод compare(), который принимает два объекта Student
  • Сравнивает студентов по их именам, используя собственный метод compareTo() класса String
  1. Теперь создадим программу, которая продемонстрирует, как использовать этот Comparator. Создайте файл с именем ComparatorDemo.java в директории ~/project:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparatorDemo {
    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));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort by name using the StudentNameComparator
        Collections.sort(students, new StudentNameComparator());

        // Print the list sorted by name
        System.out.println("\nStudents sorted by name (using Comparator):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

Эта программа:

  1. Создает список объектов Student

  2. Выводит несортированный список

  3. Сортирует список с помощью метода Collections.sort() с нашим пользовательским StudentNameComparator

  4. Выводит отсортированный список

  5. Скомпилируем и запустим наш код:

cd ~/project
javac Student.java StudentNameComparator.java ComparatorDemo.java
java ComparatorDemo

Вы должны увидеть вывод, похожий на следующий:

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

Students sorted by name (using Comparator):
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102

Как вы можете видеть, студенты теперь отсортированы по именам в алфавитном порядке, а не по среднему баллу (GPA).

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

В Java 8 были введены лямбда-выражения, которые могут упростить создание компараторов. Вместо создания отдельного класса мы можем определить логику сравнения прямо в коде.

  1. Создайте новый файл с именем LambdaComparatorDemo.java в директории ~/project:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class LambdaComparatorDemo {
    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));

        // Sort by registration number using lambda expression
        Collections.sort(students, (s1, s2) -> s1.getRegNo() - s2.getRegNo());

        // Print the list sorted by registration number
        System.out.println("Students sorted by registration number (using lambda):");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort by name using method reference
        Collections.sort(students, Comparator.comparing(Student::getName));

        // Print the list sorted by name
        System.out.println("\nStudents sorted by name (using method reference):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

Эта программа демонстрирует:

  1. Использование лямбда-выражения для создания компаратора, который сортирует студентов по регистрационному номеру

  2. Использование метода Comparator.comparing() с ссылкой на метод для создания компаратора, который сортирует студентов по имени

  3. Скомпилируйте и запустите этот код:

cd ~/project
javac Student.java LambdaComparatorDemo.java
java LambdaComparatorDemo

Вы должны увидеть вывод, похожий на следующий:

Students sorted by registration number (using lambda):
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

Students sorted by name (using method reference):
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102

Сначала студенты отсортированы по регистрационному номеру, а затем по имени.

Продвинутые техники сортировки

В реальных приложениях нам часто требуется более сложная логика сортировки, например:

  • Сортировка по нескольким критериям (например, сначала по среднему баллу (GPA), а если GPA равны, то по имени)
  • Сортировка в обратном порядке
  • Создание цепочек пользовательских компараторов (Comparator)

Рассмотрим эти продвинутые техники.

Сортировка по нескольким критериям

  1. Создайте новый файл с именем 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);
        }
    }
}

Эта программа:

  1. Создает список студентов, некоторые из которых имеют одинаковый средний балл (GPA)

  2. Создает компаратор для GPA и компаратор для имени

  3. Объединяет эти компараторы с помощью метода thenComparing()

  4. Сортирует студентов сначала по GPA, а затем по имени, если GPA равны

  5. Скомпилируйте и запустите код:

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) отсортированы в алфавитном порядке.

Сортировка в обратном порядке

  1. Создайте новый файл с именем 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);
        }
    }
}

Эта программа демонстрирует два способа сортировки в обратном порядке:

  1. Использование Collections.reverseOrder() для обращения компаратора

  2. Использование метода reversed() компаратора

  3. Скомпилируйте и запустите код:

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, а вторая сортировка показывает студентов в обратном алфавитном порядке по имени.

Сложная цепочка сортировки

  1. Создадим еще один пример, который объединяет несколько критериев и обратную сортировку. Создайте файл с именем 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);
        }
    }
}

Эта программа создает сложную цепочку сортировки, которая:

  1. Сначала сортирует студентов по GPA в порядке убывания

  2. Если GPA равны, сортирует по имени в порядке возрастания

  3. Если и GPA, и имя равны, сортирует по регистрационному номеру в порядке убывания

  4. Скомпилируйте и запустите код:

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, и Чарли идет первым по алфавиту

Это демонстрирует, как можно создать сложную многоуровневую логику сортировки, объединяя компараторы в цепочку.

Создание полноценного приложения для сортировки

Теперь, когда мы изучили интерфейс Comparable, интерфейс Comparator и различные техники сортировки, давайте объединим все это в полноценном приложении.

Мы создадим систему управления студентами, которая позволит сортировать студентов различными способами.

  1. Сначала создадим обновленную версию нашего класса Student. Эта версия будет реализовывать интерфейс Comparable и включать улучшенный метод toString() для более удобного отображения. Создайте файл с именем StudentManager.java в директории ~/project:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

class Student implements Comparable<Student> {
    private String name;
    private double gpa;
    private int regNo;
    private String major;

    public Student(String name, double gpa, int regNo, String major) {
        this.name = name;
        this.gpa = gpa;
        this.regNo = regNo;
        this.major = major;
    }

    @Override
    public int compareTo(Student other) {
        // Default natural ordering by registration number
        return this.regNo - other.regNo;
    }

    // Getters
    public String getName() {
        return name;
    }

    public double getGpa() {
        return gpa;
    }

    public int getRegNo() {
        return regNo;
    }

    public String getMajor() {
        return major;
    }

    @Override
    public String toString() {
        return String.format("%-10s | GPA: %.1f | Reg No: %-5d | Major: %-10s",
                            name, gpa, regNo, major);
    }
}

public class StudentManager {
    private List<Student> students;

    public StudentManager() {
        students = new ArrayList<>();
        // Add some sample students
        students.add(new Student("John", 3.5, 101, "Computer Science"));
        students.add(new Student("Mary", 3.8, 102, "Physics"));
        students.add(new Student("Alice", 3.5, 103, "Mathematics"));
        students.add(new Student("Bob", 3.9, 104, "Computer Science"));
        students.add(new Student("Charlie", 3.2, 105, "Physics"));
        students.add(new Student("David", 3.6, 106, "Mathematics"));
        students.add(new Student("Eve", 3.8, 107, "Biology"));
    }

    public void displayStudents() {
        System.out.println("----------------------------------------------------------");
        System.out.println("Name       | GPA   | Reg No | Major      ");
        System.out.println("----------------------------------------------------------");
        for (Student student : students) {
            System.out.println(student);
        }
        System.out.println("----------------------------------------------------------");
    }

    public void sortByNaturalOrder() {
        Collections.sort(students);
        System.out.println("\nStudents sorted by registration number (natural order):");
        displayStudents();
    }

    public void sortByName() {
        Collections.sort(students, Comparator.comparing(Student::getName));
        System.out.println("\nStudents sorted by name:");
        displayStudents();
    }

    public void sortByGpaDescending() {
        Collections.sort(students, Comparator.comparing(Student::getGpa).reversed());
        System.out.println("\nStudents sorted by GPA (descending):");
        displayStudents();
    }

    public void sortByMajorThenGpa() {
        Collections.sort(students,
            Comparator.comparing(Student::getMajor)
                     .thenComparing(Student::getGpa, Comparator.reverseOrder()));
        System.out.println("\nStudents sorted by major, then by GPA (descending):");
        displayStudents();
    }

    public static void main(String[] args) {
        StudentManager manager = new StudentManager();
        Scanner scanner = new Scanner(System.in);

        while (true) {
            System.out.println("\nStudent Manager");
            System.out.println("1. Display students (unsorted)");
            System.out.println("2. Sort by registration number");
            System.out.println("3. Sort by name");
            System.out.println("4. Sort by GPA (highest first)");
            System.out.println("5. Sort by major, then by GPA (highest first)");
            System.out.println("6. Exit");
            System.out.print("Enter your choice: ");

            int choice = scanner.nextInt();

            switch (choice) {
                case 1:
                    System.out.println("\nUnsorted student list:");
                    manager.displayStudents();
                    break;
                case 2:
                    manager.sortByNaturalOrder();
                    break;
                case 3:
                    manager.sortByName();
                    break;
                case 4:
                    manager.sortByGpaDescending();
                    break;
                case 5:
                    manager.sortByMajorThenGpa();
                    break;
                case 6:
                    System.out.println("Exiting program. Goodbye!");
                    scanner.close();
                    return;
                default:
                    System.out.println("Invalid choice. Please try again.");
            }
        }
    }
}

Это приложение:

  1. Определяет класс Student с полями имя, средний балл (GPA), регистрационный номер и специальность

  2. Реализует интерфейс Comparable для определения естественного порядка сортировки по регистрационному номеру

  3. Создает класс StudentManager, который хранит список студентов

  4. Предоставляет методы для сортировки студентов различными способами

  5. Включает простой меню-ориентированный интерфейс, позволяющий пользователю выбирать различные варианты сортировки

  6. Скомпилируйте и запустите приложение:

cd ~/project
javac StudentManager.java
java StudentManager
  1. Протестируйте приложение, попробовав различные варианты сортировки. Вот пример взаимодействия:
Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 1

Unsorted student list:
----------------------------------------------------------
Name       | GPA   | Reg No | Major
----------------------------------------------------------
John       | GPA: 3.5 | Reg No: 101   | Major: Computer Science
Mary       | GPA: 3.8 | Reg No: 102   | Major: Physics
Alice      | GPA: 3.5 | Reg No: 103   | Major: Mathematics
Bob        | GPA: 3.9 | Reg No: 104   | Major: Computer Science
Charlie    | GPA: 3.2 | Reg No: 105   | Major: Physics
David      | GPA: 3.6 | Reg No: 106   | Major: Mathematics
Eve        | GPA: 3.8 | Reg No: 107   | Major: Biology
----------------------------------------------------------

Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 3

Students sorted by name:
----------------------------------------------------------
Name       | GPA   | Reg No | Major
----------------------------------------------------------
Alice      | GPA: 3.5 | Reg No: 103   | Major: Mathematics
Bob        | GPA: 3.9 | Reg No: 104   | Major: Computer Science
Charlie    | GPA: 3.2 | Reg No: 105   | Major: Physics
David      | GPA: 3.6 | Reg No: 106   | Major: Mathematics
Eve        | GPA: 3.8 | Reg No: 107   | Major: Biology
John       | GPA: 3.5 | Reg No: 101   | Major: Computer Science
Mary       | GPA: 3.8 | Reg No: 102   | Major: Physics
----------------------------------------------------------

Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 5

Students sorted by major, then by GPA (descending):
----------------------------------------------------------
Name       | GPA   | Reg No | Major
----------------------------------------------------------
Eve        | GPA: 3.8 | Reg No: 107   | Major: Biology
Bob        | GPA: 3.9 | Reg No: 104   | Major: Computer Science
John       | GPA: 3.5 | Reg No: 101   | Major: Computer Science
David      | GPA: 3.6 | Reg No: 106   | Major: Mathematics
Alice      | GPA: 3.5 | Reg No: 103   | Major: Mathematics
Mary       | GPA: 3.8 | Reg No: 102   | Major: Physics
Charlie    | GPA: 3.2 | Reg No: 105   | Major: Physics
----------------------------------------------------------

Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 6
Exiting program. Goodbye!

Вы можете поэкспериментировать с разными вариантами сортировки, чтобы увидеть, как список студентов отображается по-разному каждый раз.

Это полноценное приложение демонстрирует мощность и гибкость интерфейсов Comparable и Comparator в Java. Оно позволяет сортировать объекты различными способами, чтобы удовлетворить различные требования вашего приложения.

Резюме

В этом практическом занятии (лабораторной работе) вы узнали, как сравнивать и сортировать объекты в Java с использованием интерфейсов Comparable и Comparator.

Покрытые ключевые концепции:

  1. Интерфейс Comparable

    • Реализация метода compareTo() для определения естественного порядка сортировки класса
    • Использование метода Collections.sort() с объектами, имеющими естественный порядок сортировки
  2. Интерфейс Comparator

    • Создание пользовательских компараторов (Comparator) для различных критериев сортировки
    • Использование метода Collections.sort() с пользовательским компаратором
    • Использование лямбда-выражений и ссылок на методы для компактного создания компараторов
  3. Продвинутые техники сортировки

    • Сортировка по нескольким критериям с использованием метода thenComparing()
    • Сортировка в обратном порядке с использованием метода Collections.reverseOrder() или reversed()
    • Создание сложных цепочек сортировки
  4. Практическое применение

    • Создание полноценной системы управления студентами с различными вариантами сортировки
    • Реализация пользовательского интерфейса для демонстрации различных возможностей сортировки

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