比较器(Comparator)和可比较接口(Comparable)

JavaBeginner
立即练习

介绍

在 Java 应用程序中,你经常需要比较和排序对象。对于整数或字符串等基本数据类型,Java 已经知道如何对它们进行比较。然而,对于自定义对象,你需要告诉 Java 应该如何对它们进行比较和排序。

Java 提供了两个接口来帮助实现这一点:

  • Comparable 接口允许类定义其自然排序规则
  • Comparator 接口提供了可用于不同排序标准的外部比较逻辑

在这个实验中,你将学习如何实现这两个接口,并使用它们以各种方式对对象集合进行排序。

理解可比较接口(Comparable)

当一个类有自然排序规则时,会使用 Comparable 接口。例如,字符串自然按字母顺序排序,整数自然按数字顺序排序。

当一个类实现 Comparable 接口时,它必须定义一个 compareTo() 方法,该方法指定了该类的实例应该如何排序。

创建一个基本的学生类

让我们创建一个简单的 Student 类,来演示如何使用 Comparable 接口。我们将定义一个学生,包含姓名、平均绩点(GPA)和注册编号。

  1. 打开 WebIDE,在 ~/project 目录下创建一个名为 Student.java 的新文件,并使用以下代码:
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 来比较学生
  • 如果当前学生的 GPA 低于另一个学生的 GPA,我们返回 -1
  • 如果当前学生的 GPA 高于另一个学生的 GPA,我们返回 1
  • 如果 GPA 相等,我们返回 0

现在,让我们创建一个简单的测试程序,看看如何使用 Comparable 接口对学生进行排序。

  1. ~/project 目录下创建一个名为 ComparableDemo.java 的新文件,并使用以下代码:
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. ~/project 目录下创建一个名为 StudentNameComparator.java 的新文件,并使用以下代码:
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 对象
  • 使用 String 类自身的 compareTo() 方法根据学生的姓名对他们进行比较
  1. 现在,让我们创建一个程序来演示如何使用这个 Comparator。在 ~/project 目录下创建一个名为 ComparatorDemo.java 的文件:
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 排序。

使用 Lambda 表达式创建比较器

Java 8 引入了 Lambda 表达式,它可以简化比较器的创建。你无需创建单独的类,就可以内联定义比较逻辑。

  1. ~/project 目录下创建一个名为 LambdaComparatorDemo.java 的新文件:
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. 使用 Lambda 表达式创建一个按注册编号对学生进行排序的比较器

  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 相同,再按姓名排序)
  • 降序排序
  • 创建自定义比较器链

让我们来探索这些高级技术。

按多个标准排序

  1. ~/project 目录下创建一个名为 MultiCriteriaDemo.java 的新文件:
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 相同的学生(Alice 和 John 的 GPA 为 3.5,Bob 和 Mary 的 GPA 为 3.8)按字母顺序排序。

降序排序

  1. ~/project 目录下创建一个名为 ReverseOrderDemo.java 的新文件:
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. 让我们再创建一个结合多个标准和逆序排序的示例。在 ~/project 目录下创建一个名为 ComplexSortingDemo.java 的文件:
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

在这个输出中:

  • Bob 和 Mary 的 GPA 都是 3.8,但 Bob 在字母顺序上排在前面
  • Alice 和 John 的 GPA 都是 3.5,但 Alice 在字母顺序上排在前面
  • Charlie 和 David 的 GPA 都是 3.2,且 Charlie 在字母顺序上排在前面

这展示了你如何通过链接比较器来创建复杂的多级排序逻辑。

构建完整的排序应用程序

既然你已经了解了 Comparable 接口、Comparator 接口以及各种排序技术,那么让我们将这些知识整合到一个完整的应用程序中。

你将创建一个学生管理系统,该系统允许以不同的方式对学生进行排序。

  1. 首先,创建一个更新版本的 Student 类。这个版本将实现 Comparable 接口,并包含一个改进的 toString() 方法,以便更好地显示信息。在 ~/project 目录下创建一个名为 StudentManager.java 的文件:
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!

你可以尝试不同的排序选项,看看每次学生列表的显示方式有何不同。

这个完整的应用程序展示了 Java 中 ComparableComparator 接口的强大功能和灵活性。它允许你以各种方式对对象进行排序,以满足应用程序的不同需求。

总结

在本次实验中,你学习了如何使用 ComparableComparator 接口在 Java 中比较和排序对象。

涵盖的关键概念如下:

  1. Comparable 接口

    • 实现 compareTo() 方法来定义类的自然排序规则
    • 对具有自然排序规则的对象使用 Collections.sort() 方法
  2. Comparator 接口

    • 为不同的排序标准创建自定义比较器
    • 使用自定义比较器调用 Collections.sort() 方法
    • 使用 Lambda 表达式和方法引用简洁地创建比较器
  3. 高级排序技术

    • 使用 thenComparing() 方法按多个标准进行排序
    • 使用 Collections.reverseOrder()reversed() 方法进行降序排序
    • 创建复杂的排序链
  4. 实际应用

    • 构建一个具有多种排序选项的完整学生管理系统
    • 实现一个用户界面来展示不同的排序功能

这些排序功能是许多 Java 应用程序的基础,特别是那些处理数据集合的应用程序。无论你是在学生管理系统中对学生进行排序,在电子商务应用程序中对订单进行排序,还是对任何其他类型的数据进行排序,本次实验中学到的技术都将帮助你实现高效且灵活的排序逻辑。