ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

内部比较器(Comparable接口)和外部比较器(Comparator接口)

2021-11-17 18:33:59  阅读:173  来源: 互联网

标签:Comparable name Comparator 对象 arr 接口 Student compareTo public


1、java.lang.Comparable

我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,之间使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决这个问题呢?

Java给所有引用数据类型的大小比较,指定了一个标准接口,就是java.lang.Comparable接口:

package java.lang;

public interface Comparable{
    int compareTo(Object obj);
}

那么我们想要使得我们某个类的对象可以比较大小,怎么做呢?步骤:

第一步:哪个类的对象要比较大小,哪个类就实现java.lang.Comparable接口,并重写方法

方法体就是你要如何比较当前对象和指定的另一个对象的大小

第二步:对象比较大小时,通过对象调用compareTo方法,根据方法的返回值决定谁大谁小。

this对象(调用compareTo方法的对象)大于指定对象(传入compareTo()的参数对象)返回正整数
this对象(调用compareTo方法的对象)小于指定对象(传入compareTo()的参数对象)返回负整数
this对象(调用compareTo方法的对象)等于指定对象(传入compareTo()的参数对象)返回零

代码示例:

class Student implements Comparable{
	private int id;
	private String name;
	private int score;
	
	//省略了构造器、get/set、toString等方法

	@Override
	public int compareTo(Object o) {
		//这些需要强制,将o对象向下转型为Student类型的变量,才能调用Student类中的属性
		Student stu = (Student) o;
		if(this.score != stu.score){
			return this.score - stu.score;
		}else{//成绩相同,按照学号比较大小
			return this.id - stu.id;
		}
	}
	
}


public class TestComparable {
	public static void main(String[] args) {
		Student s1 = new Student(1,"张三",89);
		Student s2 = new Student(2,"李四",89);
		if(s1.compareTo(s2)>0){
			System.out.println("s1>s2");
		}else if(s1.compareTo(s2)<0){
			System.out.println("s1<s2");
		}else{
			System.out.println("s1 = s2");
		}
	}
}

练习1:冒泡排序

声明一个Employee员工类,包含编号、姓名、薪资,实现Comparable接口,要求,按照薪资比较大小,如果薪资相同,按照编号比较大小。

声明一个测试类TestEmployee类,在main中创建Employee[]数组,长度为5,并且存储5个员工对象,现在要求用冒泡排序,实现对这个数组进行排序,遍历结果。

class Employee implements Comparable{		//让Employee 实现Comparable
	private int id;
	private String name;
	private double salary;
	public Employee(int id, String name, double salary) {
		super();
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	public Employee() {
		super();
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
	}
	@Override
	public int compareTo(Object o) {		//重写接口的compareTo方法
		Employee emp = (Employee) o;
		if(this.getSalary() != emp.getSalary()){
			return Double.compare(this.getSalary(), emp.getSalary());
		}
		return this.id - emp.id;
	}
}

public class TestComparable {
	public static void main(String[] args) {
		Employee[] arr = new Employee[5];
		arr[0] = new Employee(1,"张三",13000);
		arr[1] = new Employee(2,"李四",13000);
		arr[2] = new Employee(3,"王五",14000);
		arr[3] = new Employee(4,"赵六",7000);
		arr[4] = new Employee(5,"钱七",9000);
		
		//原顺序
		System.out.println("员工列表:");
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
		//冒泡排序
		for (int i = 1; i < arr.length; i++) {
			for (int j = 0; j < arr.length-i; j++) {
                //因为Employee类型实现了Comparable接口,所以有compareTo()方法
                //arr[j] 是 this 对象 
				if(arr[j].compareTo(arr[j+1])>0){
					Employee temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
		System.out.println("排序后员工列表:");
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}
}

java.util.Arrays数组工具类的public static void sort(Object[] a)就是这么实现的,只不过它使用的排序算法是效率更高快排,而不是冒泡排序,但是无论哪种排序算法,最终都要涉及到两个元素的比较大小,都需要通过元素调用compareTo()方法。

2、java.util.Comparator

思考:

(1)如果一个类,没有实现Comparable接口,而这个类你又不方便修改(例如:一些第三方的类,你只有.class文件,没有源文件),那么这样类的对象也要比较大小怎么办?

(2)如果一个类,实现了Comparable接口,也指定了两个对象的比较大小的规则,但是此时此刻我不想按照它预定义的方法比较大小,但是我又不能随意修改,因为会影响其他地方的使用,怎么办?

JDK在设计类库之初,也考虑到这种情况了,所以又增加了一个java.util.Comparator接口。

package java.util;

public interface Comparator{
    int compare(Object o1,Object o2);
}

那么我们想要比较某个类的两个对象的大小,怎么做呢?步骤:

第一步:编写一个类,我们称之为比较器类型,实现java.util.Comparator接口,并重写方法

方法体就是你要如何指定的两个对象的大小

第二步:比较大小时,通过比较器类型的对象调用compare()方法,将要比较大小的两个对象作为compare方法的实参传入,根据方法的返回值决定谁大谁小。

o1对象大于o2返回正整数
o1对象小于o2返回负整数
o1对象等于o2返回零

代码示例:一个没有实现Comparable接口的学生类

class Student{
	private String name;
	private int score;
	public Student(String name, int score) {
		super();
		this.name = name;
		this.score = score;
	}
	public Student() {
		super();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", score=" + score + "]";
	}
	
}

代码示例:定义定制比较器类

class StudentScoreCompare implements Comparator{
//方法体就是你要如何指定的两个对象的大小
	@Override
	public int compare(Object o1, Object o2) { 
	//比较大小时,通过比较器类型的对象调用compare()方法,将要比较大小的两个对象作为compare方法的实参	传入,根据方法的返回值决定谁大谁小。
		Student s1 = (Student) o1;
		Student s2 = (Student) o2;
		return s1.getScore() - s2.getScore();
		/*	
				 o1对象大于o2返回正整数
				 o1对象小于o2返回负整数
				 o1对象等于o2返回零
		*/
	}
	
}

代码示例:测试类

import java.util.Comparator;

public class TestComparator {
	public static void main(String[] args) {
		Student stu1 = new Student("张三",89);
		Student stu2 = new Student("李四",78);
		
		StudentScoreCompare ssc = new StudentScoreCompare();
		if(ssc.compare(stu1, stu2)>0){
			System.out.println(stu1 + ">" + stu2);
		}else if(ssc.compare(stu1, stu2)<0){
			System.out.println(stu1 + "<" + stu2);
		}else{
			System.out.println(stu1 + "=" + stu2);
		}
	}
}

总结

java.lang.Comparable

内部比较器不需要创建一个比较类

第一步:哪个类的对象要比较大小,哪个类就实现java.lang.Comparable接口,并重写方法

方法体就是你要如何比较当前对象和指定的另一个对象的大小

第二步:对象比较大小时,通过对象调用compareTo方法,根据方法的返回值决定谁大谁小。

this对象(调用compareTo方法的对象)大于指定对象(传入compareTo()的参数对象)返回正整数
this对象(调用compareTo方法的对象)小于指定对象(传入compareTo()的参数对象)返回负整数
this对象(调用compareTo方法的对象)等于指定对象(传入compareTo()的参数对象)返回零

2、java.util.Comparator

外部比较器 需要另外编写一个比较类

第一步:编写一个类,我们称之为比较器类型,实现java.util.Comparator接口,并重写方法

方法体就是你要如何指定的两个对象的大小

第二步:比较大小时,通过比较器类型的对象调用compare()方法,将要比较大小的两个对象作为compare方法的实参传入,根据方法的返回值决定谁大谁小。

o1对象大于o2返回正整数
o1对象小于o2返回负整数
o1对象等于o2返回零

标签:Comparable,name,Comparator,对象,arr,接口,Student,compareTo,public
来源: https://blog.csdn.net/weixin_45905210/article/details/121356802

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有