Day28 内置比较器(Comparable)与外置比较器(Comparator)
一、内置比较器------Comparable
1、概念: Comparable
是Java中的一个接口,用于实现对象自然排序的比较器。实现Comparable
接口的类可以定义自己的比较规则,从而使对象在集合中进行排序时按照指定的顺序进行排序。
2、使用方法:
-
实现Comparable接口:
- 实现类需要重写
compareTo()
方法,定义对象之间的比较规则。
Javapublic class MyClass implements Comparable<MyClass> { private int value; public int compareTo(MyClass other) { return this.value - other.value; } }
- 实现类需要重写
-
排序对象数组或集合:
- 对实现了
Comparable
接口的对象数组或集合进行排序。
JavaMyClass[] array = new MyClass[]{obj1, obj2, obj3}; Arrays.sort(array);
- 对实现了
-
自定义比较规则:
- 根据实际需求自定义比较规则,可以按照数字大小、字符串顺序等进行比较。
Javapublic int compareTo(MyClass other) { // 按照字符串长度比较 return this.name.length() - other.name.length(); }
3、举例;
需求:创建学生类,将学生类的对象添加到TreeSet中
java
import java.util.TreeSet;
public class Test03 {
/**
* 知识点:研究内置比较器的使用 -- Comparable
*
* 需求:创建学生类,将学生类的对象添加到TreeSet中
*/
public static void main(String[] args) {
TreeSet<Student> set = new TreeSet<>();
set.add(new Student("小希", '女', 27, "2401", "001"));
set.add(new Student("小空", '女', 23, "2401", "002"));
set.add(new Student("小丽", '女', 21, "2401", "003"));
set.add(new Student("小光", '女', 31, "2401", "004"));
set.add(new Student("小玲", '女', 36, "2401", "005"));
set.add(new Student("小步", '女', 29, "2401", "006"));
set.add(new Student("小奈", '女', 32, "2401", "007"));
set.add(new Student("小阳", '女', 31, "2401", "008"));
set.add(new Student("小织", '女', 27, "2401", "009"));
set.add(new Student("小伟", '男', 21, "2401", "010"));
set.add(new Student("小乐", '男', 20, "2401", "011"));
set.add(new Student("小衣", '女', 34, "2402", "001"));
set.add(new Student("小莉", '女', 23, "2402", "002"));
set.add(new Student("小亚", '女', 21, "2402", "003"));
set.add(new Student("小惠", '女', 31, "2402", "004"));
set.add(new Student("小香", '女', 27, "2402", "005"));
set.add(new Student("铃原", '女', 23, "2402", "006"));
set.add(new Student("明日", '女', 28, "2402", "007"));
set.add(new Student("小京", '女', 34, "2402", "008"));
set.add(new Student("小伟", '男', 18, "2402", "009"));
set.add(new Student("小杰", '男', 20, "2402", "010"));
for (Student stu : set) {
System.out.println(stu);
}
}
}
public class Student implements Comparable<Student>{
private String name;
private char sex;
private int age;
private String classId;
private String id;
public Student() {
}
public Student(String classId, String id) {
this.classId = classId;
this.id = id;
}
public Student(String name, char sex, int age, String classId, String id) {
this.name = name;
this.sex = sex;
this.age = age;
this.classId = classId;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClassId() {
return classId;
}
public void setClassId(String classId) {
this.classId = classId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//判断两个学生是否相同
//比较规则:班级号+学号
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj instanceof Student){
Student stu = (Student) obj;
if(this.classId.equals(stu.classId) && this.id.equals(stu.id)){
return true;
}
}
return false;
}
@Override
public String toString() {
return name + "\t" + sex + "\t" + age + "\t" + classId + "\t" + id;
}
//排序规则:按照年龄排序
@Override
public int compareTo(Student o) {
//this表示添加到TreeSet中的学生对象
//o表示TreeSet中的学生对象
return this.age - o.age;
}
}
二、外置比较器------Comparator
1、概念: Comparator
是Java中的一个接口,用于实现对象的定制排序比较器。与Comparable
接口不同的是,Comparator
接口允许在不修改对象本身的情况下,定义多种不同的排序规则。
2、理解:
通过实现Comparator
接口,可以灵活地定义多种不同的比较规则,适用于需要根据不同条件进行排序的情况。在使用Comparator
接口时,需要注意实现compare()
方法时的返回值含义,通常返回负数表示第一个对象小于第二个对象,返回正数表示第一个对象大于第二个对象,返回0表示两个对象相等。
3、使用方法:
-
实现Comparator接口:
- 实现类需要重写
compare()
方法,定义对象之间的比较规则。
javapublic class MyComparator implements Comparator<MyClass> { public int compare(MyClass obj1, MyClass obj2) { return obj1.getValue() - obj2.getValue(); } }
- 实现类需要重写
-
使用Comparator进行排序:
- 在排序时传入自定义的Comparator对象。
javaList<MyClass> list = new ArrayList<>(); list.add(obj1); list.add(obj2); Collections.sort(list, new MyComparator());
-
自定义比较规则:
- 根据实际需求自定义比较规则,可以按照数字大小、字符串顺序等进行比较。
javapublic int compare(MyClass obj1, MyClass obj2) { // 按照字符串长度比较 return obj1.getName().length() - obj2.getName().length(); }
4、举例:
需求:将学生类的对象添加到TreeSet中
场景 - 联合开发:
1.Student类是小伟开发的
2.何老师要把Student类的对象添加到TreeSet中,但是Student的排序规则不满足何老师的需求
3.何老师想的是按照名字长度排序,长度一致按照年龄排序
java
import java.util.Comparator;
import java.util.TreeSet;
public class Test04 {
/**
* 知识点:研究外置比较器的使用 -- Comparator
*
* 需求:将学生类的对象添加到TreeSet中
* 场景 - 联合开发:
* 1.Student类是巴得伟开发的
* 2.何老师要把Student类的对象添加到TreeSet中,但是Student的排序规则不满足何老师的需求
* 3.何老师想的是按照名字长度排序,长度一致按照年龄排序
*
* 比较器的优先级别:外置比较器 > 内置比较器
*/
public static void main(String[] args) {
//扩展:new Comparator 匿名内部类的使用场景!!!
TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
if(o1.equals(o2)){
return 0;
}
int nameLen1 = o1.getName().length();
int nameLen2 = o2.getName().length();
if(nameLen1 != nameLen2){
//return nameLen1 - nameLen2;
return Integer.compare(nameLen1, nameLen2);
}
int age1 = o1.getAge();
int age2 = o2.getAge();
if(age1 != age2){
return Integer.compare(age1, age2);
}
return 1;
}
});
set.add(new Student("小希", '女', 27, "2401", "001"));
set.add(new Student("小空", '女', 23, "2401", "002"));
set.add(new Student("小丽", '女', 21, "2401", "003"));
set.add(new Student("小光", '女', 31, "2401", "004"));
set.add(new Student("小玲", '女', 36, "2401", "005"));
set.add(new Student("小步", '女', 29, "2401", "006"));
set.add(new Student("小奈", '女', 32, "2401", "007"));
set.add(new Student("小阳", '女', 31, "2401", "008"));
set.add(new Student("小织", '女', 27, "2401", "009"));
set.add(new Student("小伟", '男', 21, "2401", "010"));
set.add(new Student("小乐", '男', 20, "2401", "011"));
set.add(new Student("小衣", '女', 34, "2402", "001"));
set.add(new Student("小莉", '女', 23, "2402", "002"));
set.add(new Student("小亚", '女', 21, "2402", "003"));
set.add(new Student("小惠", '女', 31, "2402", "004"));
set.add(new Student("小香", '女', 27, "2402", "005"));
set.add(new Student("铃原", '女', 23, "2402", "006"));
set.add(new Student("明日", '女', 28, "2402", "007"));
set.add(new Student("小京", '女', 34, "2402", "008"));
set.add(new Student("小伟", '男', 18, "2402", "009"));
set.add(new Student("小杰", '男', 20, "2402", "010"));
for (Student stu : set) {
System.out.println(stu);
}
}
}
ublic class Student implements Comparable<Student>{
private String name;
private char sex;
private int age;
private String classId;
private String id;
public Student() {
}
public Student(String classId, String id) {
this.classId = classId;
this.id = id;
}
public Student(String name, char sex, int age, String classId, String id) {
this.name = name;
this.sex = sex;
this.age = age;
this.classId = classId;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClassId() {
return classId;
}
public void setClassId(String classId) {
this.classId = classId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//判断两个学生是否相同
//比较规则:班级号+学号
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj instanceof Student){
Student stu = (Student) obj;
if(this.classId.equals(stu.classId) && this.id.equals(stu.id)){
return true;
}
}
return false;
}
@Override
public String toString() {
return name + "\t" + sex + "\t" + age + "\t" + classId + "\t" + id;
}
//排序规则:按照年龄排序
@Override
public int compareTo(Student o) {
//this表示添加到TreeSet中的学生对象
//o表示TreeSet中的学生对象
return this.age - o.age;
}
}
三、内置比较器(Comparable)与外置比较器(Comparator)的区别
-
Comparable接口:
- 作用:用于实现对象的自然排序,即对象本身就具有比较能力。
- 实现方式:对象类实现Comparable接口,重写compareTo()方法定义比较规则。
- 排序方式:对象在集合中进行排序时,会按照实现Comparable接口的类的compareTo()方法定义的规则进行排序。
- 局限性:一个类只能实现Comparable接口一次,无法同时支持多种排序规则。
-
Comparator接口:
- 作用:用于实现对象的定制排序,可以定义多种不同的排序规则。
- 实现方式:单独编写比较器类实现Comparator接口,重写compare()方法定义比较规则。
- 排序方式:在排序时,通过传入Comparator对象来指定使用哪种比较规则进行排序。
- 灵活性:允许在不修改对象本身的情况下定义多种排序规则,适用于需要根据不同条件进行排序的情况。
-
使用场景:
- Comparable:适用于对象自身就具有固定的比较规则,如基于某个属性的自然排序。
- Comparator:适用于需要根据不同条件进行排序,或者对第三方类进行排序时无法修改源代码的情况。
-
排序优先级:
- 当对象实现了Comparable接口时,在使用Collections.sort()等方法进行排序时,会优先使用对象自身的compareTo()方法定义的比较规则。
- 如果需要使用外置比较器的规则进行排序,则需要显式传入Comparator对象。
理解: 总的来说,Comparable接口适用于对象自身具有固定的比较规则的情况,而Comparator接口适用于需要灵活定义多种排序规则的情况。根据具体需求选择合适的比较器方式可以实现灵活、高效的对象排序。