Java中的对象,正常情况下只能进行比较:== 或 !=。不能使用 > 或 < 的,但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。如何时间? ==> 两个接口:Comparable 或 Comparator。

1. Comparable 接口

1.1 String 和包装类

Comparable 中只含有一个抽象方法:compareTo。接口源码如下:

  1. public interface Comparable<T> {
  2. public int compareTo(T o);
  3. }
  • String包装类 等实现了 Comparable 接口,都重写了 compareTo 方法,各自有各自的比较方法。
  • String包装类 重写 compareTo(obj) 方法,让它进行了从小到大的升序排列,String是按字典序。
  • 重写 compareTo(obj) 的规则为:
    • 如果当前对象 this 大于形参对象 obj,则返回正整数
    • 如果当前对象 this 小于形参对象 obj,则返回负整数
    • 如果当前对象 this 等于形参对象 obj,则返回 ```java package pkg9;

public class CompareTest { public static void main(String[] args) { String str1 = “abc” ; String str2 = “bcd” ; System.out.println(str1.compareTo(str2)); // str1 < str2 应该返回一个负数 } }

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2643809/1626688198365-a9b0e902-87ef-4ff0-b6dc-913616840e15.png#clientId=u66d1f65e-5ecf-4&from=paste&height=90&id=ud8906c2d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=90&originWidth=597&originalType=binary&ratio=1&size=7426&status=done&style=none&taskId=u614f10b5-027c-404b-aa78-9be35998e67&width=597)<br />这里不能不提一个类:
```java
import java.util.Arrays;
该类中有很多专门用于数组的方法,其中正是因为 compareTo 方法的存在,该类才有很多**静态 sort 方法**对各种数据类型的数组进行升序排序。<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2643809/1626688444835-f805709f-2b2d-47bf-9375-cf92b5a10277.png#clientId=u66d1f65e-5ecf-4&from=paste&height=192&id=uceec3fee&margin=%5Bobject%20Object%5D&name=image.png&originHeight=192&originWidth=577&originalType=binary&ratio=1&size=25784&status=done&style=none&taskId=u72460799-f8f0-42a4-858a-9387731ac27&width=577)<br />如下下列代码就调用了 sort 方法来对 String[] 进行了此排序。
package pkg9;

import java.util.Arrays;

public class CompareTest {
    public static void main(String[] args) {
        String[] strs = new String[]{"AA","CC","MM","BB"} ;
        Arrays.sort(strs);
        System.out.println(Arrays.toString(strs));    // 用 Arrays 的 toString 方法输出数组
    }
}

image.png

1.2 自定义类

对于自定义来说,如果想要进行 sort 排序,则必须实现 Comparable 接口,即实现 compareTo 方法,否则无法使用 sort 排序,运行时会报错。
没有实现 Comparable 的类:

package pkg9;

public class Good {
    private int price ;
    private String name ;

    public Good(int price, String name) {
        this.price = price;
        this.name = name;
    }
}

image.png
可以看到,对 Good 数组进行 sort 排序,编译并不会报错。但是,在运行时就会出现异常(ClassCastException):
image.png
所以自定义类一定要实现 Comparable 接口。然后重写(实现)compareTo(obj) 方法。在方法中自定义比较方式,当当前对象和入参对象怎么怎么样时返回一个正整数,怎么怎么样时返回一个负整数,怎么怎么样时返回一个零。
比如,对上述 Good 类来自定义比较器,如果当前对象价格更高,则返回1,更低则返回-1,相等则返回0:

    @Override
    public int compareTo(Object o) {
        if (o instanceof Good){   // 首先得判断是否为想比较的类
            Good o1 = (Good) o;
            return Double.compare(this.price,o1.price) ;
        }
        else {
            throw new RuntimeException("传入数据类型不一致") ;
        }
    }

image.png


2. Comparator 比较器接口

Comparator 也是一个比较接口,但是不需要类来实现。在Arrays的 sort 方法中,可以传入两个参数。一个就是要排序的对象数组,另一个就是 Comparator 的匿名实现对象(比较器),在比较器中重写 compare方法就行。
Good 类:

public class Good  {
    private int price ;
    private String name ;

    public Good(int price, String name) {
        this.price = price;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Good{" +
                "price=" + price +
                ", name='" + name + '\'' +
                '}';
    }

    public int getPrice() {
        return price;
    }

    public String getName() {
        return name;
    }

image.png
compare 中,如果return > 0 ,sort 就将 o1 排在 o2 后面,如果 return < 0,就将 o2 排在 o1 后面,如果return = 0 ,就不排序。
使用比较器能够非常方便快速的定义排序标准,从名字上就可以看出来,Comparable 指能比较的,所以需要类来实现,以代表改类是可以比较的;而 Comparator 则是个实在的比较器,创建一个匿名实现类的对象即可完成比较。
一般而言,对数组进行排序都是用比较器接口 Comparator 而不是 Comparable 比较器。