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接口适用于需要灵活定义多种排序规则的情况。根据具体需求选择合适的比较器方式可以实现灵活、高效的对象排序。

相关推荐
姝孟3 分钟前
C++——类和对象
开发语言·c++
小白学大数据3 分钟前
Snapchat API 访问:Objective-C 实现示例
开发语言·macos·objective-c
gopher95114 分钟前
go语言基础入门(一)
开发语言·golang
masa01010 分钟前
JavaScript--JavaScript基础
开发语言·javascript
Amor风信子10 分钟前
【力扣】2376. 统计特殊整数
算法·leetcode·职场和发展
极客小张11 分钟前
基于正点原子Linux开发板的智能监控与家电控制系统设计:深度解析Video4Linux和TCP/IP技术栈
linux·运维·c++·物联网·网络协议·tcp/ip·算法
拓端研究室TRL13 分钟前
Python用TOPSIS熵权法重构粮食系统及期刊指标权重多属性决策MCDM研究|附数据代码...
开发语言·python·重构
JustCouvrir1 小时前
代码随想录算法训练营Day5
算法
一只特立独行的猪6111 小时前
Java面试——集合篇
java·开发语言·面试
大得3692 小时前
go注册中心Eureka,注册到线上和线下,都可以访问
开发语言·eureka·golang