深入理解Java比较器(Comparable和Comparator)
文章目录
- 深入理解Java比较器(Comparable和Comparator)
- 一、深入 Comparable
- 1、理解Comparable 接口定义
- 二、比较Comparator 比较器接口
- 2.1、深入Comparator接口原码
- 2.2具体代码示例
- 三、理解Comparator 和 Comparable 比较
在java中经常涉及到对象数组的比较比较的情况,常见的深入有两种方法来处理:
- 继承comparable接口,并实现compareTo()方法
- 定义一个单独的理解对象比较器,继承自Comparator接口,比较实现compare()方法
一、深入 Comparable
若一个类实现了Comparable接口,理解就意味着该类支持排序。比较实现了 Comparable接口的深入类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序。
此外,理解实现此接口的比较对象可以用作有序映射中的键或有序集合中的集合,无需指定比较器。
此接口只有一个方法compare,比较此对象与指定对象的顺序,如果该对象小于、等于或大于指定 对象,则分别返回负整数、零或正整数。
1、Comparable 接口定义
Comparable 接口仅仅只包括一个函数,如下
package java.lang;import java.util.*;public interface Comparable { //必须实现的抽象方法 public int compareTo(T o);}
说明:根据这个方法的返回值来判断
大于0:说明前一个比后一个大
小于0:说明前一个小于后一个
等于0:说明这两个一样大
示例:
这里有一个员工类Employee1,我们需要堆员工实体对员工的工资进行排序,所以这里用实现Comparable接口,重写compareTo方法
import java.util.Arrays;public class Employee1 implements Comparable{ private String name; private double salary; public Employee1(String name , double salary){ this.name = name; this.salary = salary; } public Employee1(String name , double salary, int height){ this.name = name; this.salary = salary; } 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; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } @Override public String toString() { return "Employee1{ " + "name='" + name + '\'' + ", salary=" + salary + '}'; } /** * 重写排序规则: * 定义我们的排序规则,用salary来排序 * @param other * @return */ @Override public int compareTo(Employee1 other) { return Double.compare(salary,other.salary); }}
此时:我们重写了compareTo方法,可以看出是用成员变量salary进行了比较,当前一个对象小于后一个对象时,返回小于0,反之大于0,等于则返回0.
测试类:
public static void main(String[] args) { Employee1[] temp=new Employee1[4]; temp[0]=new Employee1("张三",150); temp[1]=new Employee1("李四",120); temp[2]=new Employee1("王五",135); temp[3]=new Employee1("小花",80); Arrays.sort(temp); for (Employee1 employee1 : temp) { System.out.println(employee1.toString()); } }
输出结果:
总结:
此时因为我们已经重写了compareTo方法,这里我们用实现Comparable的方法进行了对象的排序。
二、Comparator 比较器接口
背景:
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。
2.1、Comparator接口原码
特别说明
若一个类要实现Comparator接口:它一定要实现compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
为什么可以不实现 equals(Object obj) 函数呢? 因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。
package java.util;public interface Comparator { int compare(T o1, T o2); boolean equals(Object obj);}
int compare()方法
返回值为:
小于0–>前一个对象小于后一个对象
大于0–>前一个对象大于后一个对象
等于0–>前一个对象等于后一个对象
2.2具体代码示例
背景
此时,我们在Employee1类的基础上,我们再添加一个升高,但是这个类的依旧实现了Comparable接口,重写了compareTo方法,并且这个方法按照工资薪水排序,此时我们如何能都不改变代码的前提下,重新对升高排序呢?
此时就引入了Comparator接口,我们实现这个接口的int compare方法,具体如下
public class Employee implements Comparable{ private String name; private double salary; private int height; public Employee(String name , double salary){ this.name = name; this.salary = salary; } public Employee(String name , double salary, int height){ this.name = name; this.salary = salary; this.height= height; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getSalary() { return salary; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public void setSalary(Double salary) { this.salary = salary; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } /** * 重写排序规则: * 定义我们的排序规则,用salary来排序 * @param other * @return */ @Override public int compareTo(Employee other) { return Double.compare(salary,other.salary); }}
编写测试类:
public class EmployeeSortTest { public static void main (String[] args) { Employee[] staff = new Employee[4]; staff[0] = new Employee ("张三" , 35000,175) ; staff[1] = new Employee ("李四" , 75000,165); staff[2] = new Employee ("王五" , 38000,180) ; staff[3] = new Employee ("小六" , 23000,153) ; //核心排序代码,对升高进行排序 Arrays.sort(staff, Comparator.comparingInt(Employee::getHeight)); //遍历数组结果 for (Employee e : staff){ System.out.println("name=" + e.getName() + " ,salary=" + e.getSalary()+" ,height="+e.getHeight()); } }}
对于核心排序代码,我们也可以用lambda表达式来编写:
Arrays.sort(staff,((o1, o2) ->{ if(o1.getHeight()==o2.getHeight()){ return 0; } return o1.getHeight()-o2.getHeight(); })) ;
原因;
从Arrays.sort()源码的角度分析,sort方法接收的参数类型,一个为数组类型,一个为Comparator对象,因为Comparator为接口所以不能实例化,但是我们可以用多态来指向它,我们可以声明Comparator的实现类对象指向这个接口,此时就可以调用这个接口。
当我们用lambda表达式时,也是创建了这个Comparator接口的具体实现方法,所以两者都可以进行排序,看读者的自己。
输出结果:
此时我们的这个数组对象就已经按照升高排序,实现需求。
三、Comparator 和 Comparable 比较
Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。
而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
的自己。