文章目录
Java 中 Comparable 和 Comparator 比较
Comparable 简介
Comparable 是排序接口。
若一个类实现了Comparable接口,就意味着“该类支持排序”。 即然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序。
此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。
Comparable 定义
Comparable 接口仅仅只包括一个函数,它的定义如下:
package java.lang;
import java.util.*;
public interface Comparable<T> {
public int compareTo(T o);
}
说明:
假设我们通过 x.compareTo(y) 来“比较x和y的大小”。
- 若返回“负数”,意味着“x比y小”;
- 返回“零”,意味着“x等于y”;
- 返回“正数”,意味着“x大于y”。
Comparator 简介
Comparator 是比较器接口。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。
也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。
Comparator 定义
Comparator 接口仅仅只包括两个函数,它的定义如下:
package java.util;
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
说明:
- 若一个类要实现Comparator接口:它一定要重写compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
为什么可以不实现 equals(Object obj) 函数呢? 因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。
Comparator 和 Comparable 区别
Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。
而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
我们不难发现:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
我们通过一个测试程序来对这两个接口进行说明。源码如下:
实现Comparable接口,重写compareTo
package wenhua.project;
import java.util.ArrayList;
import java.util.Collections;
/**
* @author wenhua
* @date 2022年02月17日 10:21
*/
public class Person implements Comparable<Person>{
// 声明属性
private int age ;
private String name;
// 生成构造方法
public Person() {}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
/**
* 实现Comparable接口,重写compareTo方法
* @param person
* @return
*/
@Override
public int compareTo(Person person) {
// 实现类排序
return name.compareTo(person.name);// 等价于return this.name - person.name;
}
public static void main(String[] args) {
// 新建ArrayList(动态数组)
ArrayList<Person> list = new ArrayList<Person>();
// 添加对象到ArrayList中
list.add(new Person(20,"ccc"));
list.add(new Person(30,"AAA"));
list.add(new Person(10,"bbb"));
list.add(new Person(40,"ddd"));
System.out.println("排序之前:"+list.toString());
// 通过集合静态类Collections调用sort进行排序
Collections.sort(list);
System.out.println("排序之后:"+list.toString());
}
运行结果:
排序之前:[Person{age=20, name='ccc'}, Person{age=30, name='AAA'}, Person{age=10, name='bbb'}, Person{age=40, name='ddd'}]
排序之后:[Person{age=30, name='AAA'}, Person{age=10, name='bbb'}, Person{age=20, name='ccc'}, Person{age=40, name='ddd'}]
实现Comparator,重写compare方法
package wenhua.project;
import java.util.Arrays;
import java.util.Comparator;
/**
* @author wenhua
* @date 2022年02月17日 10:21
*/
public class Person implements Comparator<Person> {
// 声明属性
private int age ;
private String name;
// 生成构造方法
public Person() {}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
// 生成get方法
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
/**
* 实现Comparator接口,重写compare方法
* @param o1
* @param o2
* @return
*/
@Override
public int compare(Person o1, Person o2) {
// 升序
return o1.getAge()-o2.getAge();
}
public static void main(String[] args) {
// 指定比较器,对指定的对象数组进行排序
Person[] list = new Person[4];
list[0] = new Person(20,"ccc");
list[1] = new Person(30,"AAA");
list[2] = new Person(10,"bbb");
list[3] = new Person(40,"ddd");
// 注此时数组长度和存储数据长度一致,否则出现运行时错误:NullPointerException
/* 方式一:
创建实现了Comparator接口的子类Person(数组的数据类型)有排序功能,并重写其compare方法
*/
Arrays.sort(list,new Person());
System.out.println("方式一:升序输出:"+Arrays.toString(list));
/* 方式二:
直接实现Comparator接口创建匿名对象,重写compare方法
*/
Arrays.sort(list,new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o2.getAge()-o1.getAge();// 降序
}
});
System.out.println("方式二:降序输出:"+Arrays.toString(list));
}
}
运行结果:
方式一:升序输出:[Person{age=10, name='bbb'}, Person{age=20, name='ccc'}, Person{age=30, name='AAA'}, Person{age=40, name='ddd'}]
方式二:降序输出:[Person{age=40, name='ddd'}, Person{age=30, name='AAA'}, Person{age=20, name='ccc'}, Person{age=10, name='bbb'}]
总结
Comparable接口直接实现且重写其compareTo方法,可直接通过Collections.sort(Object o)或Arrays.sort(Object o)方法调用,否则报错。
Comparator接口可以实现成一个排序类,在调用Arrays.sort()时必须传入new Comparator接口该对象(或子类该对象)的比较器。
参考文章:https://www.cnblogs.com/skywang12345/p/3324788.html