Day28 内置比较器(Comparable)与外置比较器(Comparator)

Day28 内置比较器(Comparable)与外置比较器(Comparator)

一、内置比较器------Comparable

1、概念: Comparable是Java中的一个接口,用于实现对象自然排序的比较器。实现Comparable接口的类可以定义自己的比较规则,从而使对象在集合中进行排序时按照指定的顺序进行排序。

2、使用方法:

  1. 实现Comparable接口

    • 实现类需要重写compareTo()方法,定义对象之间的比较规则。
    Java 复制代码
    public class MyClass implements Comparable<MyClass> {
        private int value;
    
        public int compareTo(MyClass other) {
            return this.value - other.value;
        }
    }
  2. 排序对象数组或集合

    • 对实现了Comparable接口的对象数组或集合进行排序。
    Java 复制代码
    MyClass[] array = new MyClass[]{obj1, obj2, obj3};
    Arrays.sort(array);
  3. 自定义比较规则

    • 根据实际需求自定义比较规则,可以按照数字大小、字符串顺序等进行比较。
    Java 复制代码
    public 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、使用方法:

  1. 实现Comparator接口

    • 实现类需要重写compare()方法,定义对象之间的比较规则。
    java 复制代码
    public class MyComparator implements Comparator<MyClass> {
        public int compare(MyClass obj1, MyClass obj2) {
            return obj1.getValue() - obj2.getValue();
        }
    }
  2. 使用Comparator进行排序

    • 在排序时传入自定义的Comparator对象。
    java 复制代码
    List<MyClass> list = new ArrayList<>();
    list.add(obj1);
    list.add(obj2);
    Collections.sort(list, new MyComparator());
  3. 自定义比较规则

    • 根据实际需求自定义比较规则,可以按照数字大小、字符串顺序等进行比较。
    java 复制代码
    public 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)的区别

  1. Comparable接口

    • 作用:用于实现对象的自然排序,即对象本身就具有比较能力。
    • 实现方式:对象类实现Comparable接口,重写compareTo()方法定义比较规则。
    • 排序方式:对象在集合中进行排序时,会按照实现Comparable接口的类的compareTo()方法定义的规则进行排序。
    • 局限性:一个类只能实现Comparable接口一次,无法同时支持多种排序规则。
  2. Comparator接口

    • 作用:用于实现对象的定制排序,可以定义多种不同的排序规则。
    • 实现方式:单独编写比较器类实现Comparator接口,重写compare()方法定义比较规则。
    • 排序方式:在排序时,通过传入Comparator对象来指定使用哪种比较规则进行排序。
    • 灵活性:允许在不修改对象本身的情况下定义多种排序规则,适用于需要根据不同条件进行排序的情况。
  3. 使用场景

    • Comparable:适用于对象自身就具有固定的比较规则,如基于某个属性的自然排序。
    • Comparator:适用于需要根据不同条件进行排序,或者对第三方类进行排序时无法修改源代码的情况。
  4. 排序优先级

    • 当对象实现了Comparable接口时,在使用Collections.sort()等方法进行排序时,会优先使用对象自身的compareTo()方法定义的比较规则。
    • 如果需要使用外置比较器的规则进行排序,则需要显式传入Comparator对象。

    理解: 总的来说,Comparable接口适用于对象自身具有固定的比较规则的情况,而Comparator接口适用于需要灵活定义多种排序规则的情况。根据具体需求选择合适的比较器方式可以实现灵活、高效的对象排序。

相关推荐
JavaGuide3 小时前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户3721574261353 小时前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源3 小时前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
CoovallyAIHub3 小时前
中科大DSAI Lab团队多篇论文入选ICCV 2025,推动三维视觉与泛化感知技术突破
深度学习·算法·计算机视觉
Java中文社群3 小时前
有点意思!Java8后最有用新特性排行榜!
java·后端·面试
代码匠心4 小时前
从零开始学Flink:数据源
java·大数据·后端·flink
间彧4 小时前
Spring Boot项目中如何自定义线程池
java
间彧4 小时前
Java线程池详解与实战指南
java
用户298698530144 小时前
Java 使用 Spire.PDF 将PDF文档转换为Word格式
java·后端
NAGNIP4 小时前
Serverless 架构下的大模型框架落地实践
算法·架构