介绍
在许多应用程序中,比较对象并对其进行排序是一个常见的需求。Java 提供了两个接口,Comparator
和 Comparable
,用于允许类根据某些标准定义其自身的自然顺序。
在许多应用程序中,比较对象并对其进行排序是一个常见的需求。Java 提供了两个接口,Comparator
和 Comparable
,用于允许类根据某些标准定义其自身的自然顺序。
Comparable
接口要实现 Comparable
接口,类需要定义其自然排序规则。这是通过重写 compareTo()
方法来实现的。compareTo()
方法返回一个负整数、零或正整数,分别表示调用对象小于、等于或大于方法的参数。
以下代码块展示了一个实现 Comparable
接口的 Student
类的示例:
class Student implements Comparable<Student> {
private String name;
private int gpa;
private int regNo;
public Student(String name, int gpa, int regNo) {
this.name = name;
this.gpa = gpa;
this.regNo = regNo;
}
// 重写 compareTo() 方法
@Override
public int compareTo(Student other) {
return this.gpa - other.gpa;
}
// Getters 和 setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGpa() {
return gpa;
}
public void setGpa(int gpa) {
this.gpa = gpa;
}
public int getRegNo() {
return regNo;
}
public void setRegNo(int regNo) {
this.regNo = regNo;
}
}
在 compareTo()
方法中,我们根据学生的 gpa
定义了排序规则。
Collections.sort()
方法对对象进行排序在实现了 compareTo()
方法后,我们可以使用 Collections.sort()
方法对 Student
对象列表进行排序。以下代码块展示了这一过程:
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
Collections.sort(studentList);
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
Collections.sort()
方法会根据 compareTo()
方法定义的规则,按照 gpa
的升序对列表中的 Student
对象进行排序。
Comparator
接口在某些情况下,你可能希望根据不同的标准对对象进行排序。在这种情况下,我们可以使用 Comparator
接口。
Comparator
接口提供了一个 compare()
方法,该方法接受两个参数,并返回一个负整数、零或正整数,分别表示第一个参数小于、等于或大于第二个参数。
以下是一个 Student
类的示例,其中实现了 Comparator
接口以按名称排序:
class StudentNameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
}
Comparator
对对象进行排序要使用 Comparator
对对象进行排序,可以使用 Collections
类的 sort()
方法。sort()
方法有一个重载版本,接受一个类型为 Comparator
的额外参数。
以下是一个使用 StudentNameComparator
类按名称对 Student
对象进行排序的示例:
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
StudentNameComparator nameComparator = new StudentNameComparator();
Collections.sort(studentList, nameComparator);
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
Collections.sort()
方法使用 nameComparator
对象按字母顺序对 Student
对象进行排序。
在某些情况下,你可能希望根据多个条件对对象进行排序。例如,你可能希望先按 gpa
对 Student
对象进行排序,然后再按名称排序。
你可以通过使用 Comparator
接口的 thenComparing()
方法将多个比较器链接起来实现这一点。
以下是一个 Student
类的示例,其中包含一个按 gpa
和名称排序的比较器:
class StudentGpaNameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
int gpaCompare = s1.getGpa() - s2.getGpa();
if (gpaCompare != 0) {
return gpaCompare;
}
return s1.getName().compareTo(s2.getName());
}
}
StudentGpaNameComparator
类根据 Student
对象的 gpa
进行比较。如果 gpa
相同,则通过比较 Student
对象的名称来打破平局。
thenComparing()
按多个条件对对象进行排序要按多个条件对对象进行排序,可以使用 Comparator
接口的 thenComparing()
方法。thenComparing()
方法接受一个 Comparator
对象作为参数,并返回一个新的 Comparator
对象,该对象将之前的 Comparator
与新的 Comparator
链接起来。
以下是一个使用 StudentGpaNameComparator
类对 Student
对象进行排序的示例:
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
studentList.add(new Student("Joe", 4, 104));
StudentGpaNameComparator gpaNameComparator = new StudentGpaNameComparator();
Collections.sort(studentList, gpaNameComparator);
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
Collections.sort()
方法使用 gpaNameComparator
对象根据 Student
对象的 gpa
进行排序,然后再按名称排序。
默认情况下,Collections.sort()
方法按升序对对象进行排序。要按降序对对象进行排序,可以使用 Comparator
接口的 reverseOrder()
方法。该方法返回一个 Comparator
对象,该对象按自然顺序的相反顺序对对象进行排序。
以下是一个按 GPA 降序对 Student
对象进行排序的示例:
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
studentList.add(new Student("Joe", 4, 104));
Comparator<Student> reverseGpaComparator = Collections.reverseOrder();
Collections.sort(studentList, new StudentGpaComparator().thenComparing(new StudentNameComparator()).reversed());
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
reverseGpaComparator
对象用于按 gpa
降序对 Student
对象进行排序。thenComparing()
方法用于按名称作为平局决胜条件对 Student
对象进行排序。最后,reversed()
方法用于反转整个比较的顺序。
现在你已经了解了如何使用 Comparable
和 Comparator
对对象进行排序,让我们将所有内容整合到一个 Java 类中:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Student implements Comparable<Student> {
private String name;
private int gpa;
private int regNo;
public Student(String name, int gpa, int regNo) {
this.name = name;
this.gpa = gpa;
this.regNo = regNo;
}
// 重写 compareTo() 以实现自然排序
@Override
public int compareTo(Student other) {
return this.gpa - other.gpa;
}
// Getter 和 Setter 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGpa() {
return gpa;
}
public void setGpa(int gpa) {
this.gpa = gpa;
}
public int getRegNo() {
return regNo;
}
public void setRegNo(int regNo) {
this.regNo = regNo;
}
}
class StudentNameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
}
class StudentGpaComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return s1.getGpa() - s2.getGpa();
}
}
class StudentGpaNameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
int gpaCompare = s1.getGpa() - s2.getGpa();
if (gpaCompare != 0) {
return gpaCompare;
}
return s1.getName().compareTo(s2.getName());
}
}
public class ComparatorComparable {
public static void main(String[] args) {
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("John", 3, 101));
studentList.add(new Student("Mary", 4, 102));
studentList.add(new Student("Alice", 3, 103));
studentList.add(new Student("Joe", 4, 104));
// 使用 compareTo() 按 GPA 排序
Collections.sort(studentList);
System.out.println("按 GPA 排序:");
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
// 使用 Comparator 按名称排序
StudentNameComparator nameComparator = new StudentNameComparator();
Collections.sort(studentList, nameComparator);
System.out.println("\n按名称排序:");
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
// 使用 Comparator 链按 GPA 和名称排序
StudentGpaNameComparator gpaNameComparator = new StudentGpaNameComparator();
Collections.sort(studentList, gpaNameComparator);
System.out.println("\n按 GPA 和名称排序:");
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
// 使用 Comparator 链按 GPA 降序和名称升序排序
Comparator<Student> reverseGpaComparator = Collections.reverseOrder();
Collections.sort(studentList, new StudentGpaComparator().thenComparing(new StudentNameComparator()).reversed());
System.out.println("\n按 GPA 降序和名称升序排序:");
for (Student s : studentList) {
System.out.println(s.getName() + ", GPA: " + s.getGpa());
}
}
}
要运行代码示例,请将文件保存为 ComparatorComparable.java
,然后在终端中运行以下命令:
cd ~/project
javac ComparatorComparable.java
java ComparatorComparable
你应该会看到根据不同排序条件排序后的 Student
对象的输出。
在本实验中,你学习了如何在 Java 中使用 Comparable
和 Comparator
接口,根据不同的条件对对象进行排序。
具体来说,你学习了如何实现 Comparable
接口,以基于类的条件定义自然排序。你还学习了如何使用 Comparator
接口,根据不同的条件定义排序,并链式组合多个比较器。
最后,你学习了如何使用 Collections.sort()
方法对对象进行排序,以及如何使用 reverseOrder()
方法对对象进行降序排序。