目录
Java 比较器Comparable 和 Comparator详解
1、概述
2、Comparable 和 Comparator 实例演示
3、总结
Comparable 和 Comparator接口都可以用来实现集合中元素的比较、排序;
Comparator位于包java.util下,而Comparable位于包java.lang下,Comparable接口将比较代码嵌入自身类中,而后者在一个独立的类中实现比较。
像Integer、String等这些基本类型的Java封装类都已经实现了Comparable接口,这些类对象本身就支持自比较,直接调用Collections.sort()就可以对集合中元素的排序,无需自己去实现Comparable接口。
而有些自定义类的List序列,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较,也就是指定使用Comparator(临时规则排序,也称作专门规则排序),如果不指定Comparator,那么就用自然规则排序,这里的自然顺序就是实现Comparable接口设定的排序方式。
注意:如果一个对象没有实现Comparator 和Comparable接口 ,就不能进行排序,否则会报错java.lang.ClassCastException。
(1)定义了一个Car类,他有三个属性,车名,价格,生产年份。并实现了Comparable 实现了一个compareTo方法,按照车的价格进行排序。
public class Car implements Comparable{
private String name;
private int price;
private int age;
public Car(String name , int price , int age){
this.name = name;
this.price = price;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", price=" + price +
", age=" + age +
'}';
}
@Override
public int compareTo(Car car) {
return this.price - car.price;
}
}
(2)测试类。实现按照车的价格进行排序。
import java.util.ArrayList;
import java.util.Arrays;
public class Test {
public static void main(String args[]){
ArrayList list = new ArrayList<>();
list.add(new Car("宝马" , 12 , 2019));
list.add(new Car("大众" , 10 , 2015));
list.add(new Car("蓝比基尼" , 50 , 2018));
Car[] cars = list.toArray(new Car[list.size()]);
Arrays.sort(cars);
for(Car car : cars){
System.out.println(car);
}
}
}
结果:
Car{name='大众', price=10, age=2015}
Car{name='宝马', price=12, age=2019}
Car{name='蓝比基尼', price=50, age=2018}
(3)如果我想按照车的生产年份进行从大到小的排序呢。有两种方法,一种就是重新修改Car类中的compareTo方法。第二种方法就是使用Comparator 创建一个外部排序,实现compare方法。如下:
public class Test {
public static void main(String args[]){
ArrayList list = new ArrayList<>();
list.add(new Car("宝马" , 12 , 2019));
list.add(new Car("大众" , 10 , 2015));
list.add(new Car("蓝比基尼" , 50 , 2018));
Car[] cars = list.toArray(new Car[list.size()]);
Arrays.sort(cars, new Comparator() {//添加一个外部排序器即可
@Override
public int compare(Car car, Car t1) {
return t1.getAge() - car.getAge();
}
});
for(Car car : cars){
System.out.println(car);
}
}
}
结果:
Car{name='宝马', price=12, age=2019}
Car{name='蓝比基尼', price=50, age=2018}
Car{name='大众', price=10, age=2015}
哈哈,是不是感觉Comparable 和 Comparator 就那样。。。。。。。
两种比较器的区别
(1)Comparable是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”。而Comparator是比较器,我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
(2)Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
(3)两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。
如何确认比价的类型
(1)如果我们是用方法中的前者减去后者,那么可以认为是升序,即从小到大。如上面的第一个实例:
@Override
public int compareTo(Car car) { //升序排序
return this.price - car.price;
}
(2)如果我们是用方法中的前者减去后者,那么可以认为是升序,即从小到大。如上面的第二个实例:
Arrays.sort(cars, new Comparator() {//添加一个外部排序器即可
@Override
public int compare(Car car, Car t1) {
return t1.getAge() - car.getAge(); //降序排序
}
});