Comparable和Comparator接口

Comparable和Comparator接口

1.自然排序 Comparable接口

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class'compareTo method is referred to as its natural comparison method.

简言之:实现该接口的类能够根据自己重写的compareTo方法的规则来实现排序,这种排序叫做自然排序。 Comparable 接口中只提供了一个方法:compareTo(Object obj) ,该方法的返回值是 int 。如果返回值为正数,则表示当前对象(调用该方法的对象)比 obj 对象“大”;反之“小”;如果为零的话,则表示两对象相等

  • 实现Comaparable接口
  • 重写compareTo方法

代码示例

@Data
@AllArgsConstructor
public class Person implements Comparable<Person>{
    private String name;
    private int age;

    public int compareTo(Person o) {
        if (this.age < o.age) {
            return 1;
        } else if (this.age > o.age) {
            return -1;
        }
        return 0;
    }
}
public class TestComparable {

    public static void main(String[] args) {
        test1();
    }

    public static void test1() {
        TreeMap<Person, Object> treeMap = new TreeMap<>();
        treeMap.put(new Person("aaa", 19), "20");
        treeMap.put(new Person("bbb", 4), "20");
        treeMap.put(new Person("ccc", 98), "20");
        treeMap.put(new Person("ddd", 20), "20");
        System.out.println(treeMap);
    }
}

输出结果

{Person(name=ccc, age=98)=20, Person(name=ddd, age=20)=20, Person(name=aaa, age=19)=20, Person(name=bbb, age=4)=20}

可见Person对象的排序规则是按照年龄递减的

总结

  • Comparable接口是作用于某个实体类的,使该实体类能够按照compareTo方法规定的规则进行排序
  • Comparable具有局限性,因为一个实体类只能重写一个compareTo方法,也就是使用该接口只能定义一种排序规则。
  • 如果上面的Person对象要求既要按照名字排序,又要按照年龄排序,那么Comparable接口就无法满足,这时候就需要使用Comparator接口来实现了。

2. 比较器排序 Comparator接口

上面我提到了,之所以提供比较器排序接口,是因为有时需要对同一对象进行多种不同方式的排序,这点自然排序 Comparable 不能实现。另外, Comparator 接口的一个好处是将比较排序算法和具体的实体类分离了。

  • 创建一个新的类实现Comparator接口(也可以直接使用匿名内部类)
  • 重写compare方法
public class TestComparable {

    public static void main(String[] args) {
        test3();
        test4();
    }

    /**
     * Arrays.sort 还有种重载形式:sort(T[] a, Comparator<? super T> c) 
     * Comparator 比较器 通常作用于装实体类的集合上
     * 如果一个系统中,既需要根据person的姓名排序,又需要根据person的年龄排序
     * 这时候令Person类实现Comparable接口 只能完成一种排序方式就不能实现需求了
     * 所以这时候需要使用Comparator接口
     */
    public static void test3() {
        Person p1 = new Person("aaa", 19);
        Person p2 = new Person("bbb", 4);
        Person p3 = new Person("ccc", 98);
        Person p4 = new Person("ddd", 20);
        Person[] person = {p1, p2, p3, p4};
	// 名字按照升序排序
        Arrays.sort(person, (person1, person2) -> person1.getName().compareTo(person2.getName()));
        System.out.println(Arrays.toString(person));
    }

    public static void test4() {
        Person p1 = new Person("aaa", 19);
        Person p2 = new Person("bbb", 4);
        Person p3 = new Person("ccc", 98);
        Person p4 = new Person("ddd", 20);
        Person[] person = {p1, p2, p3, p4};
	// 年龄按照升序排序
        Arrays.sort(person, (person1, person2) -> person1.getAge() - person2.getAge());
        System.out.println(Arrays.toString(person));
    }
}

输出结果:

[Person(name=aaa, age=19), Person(name=bbb, age=4), Person(name=ccc, age=98), Person(name=ddd, age=20)]
[Person(name=bbb, age=4), Person(name=aaa, age=19), Person(name=ddd, age=20), Person(name=ccc, age=98)]

总结

  • Comparable是表示该类可以比较,是该类的具体对象以一种方式和其他对象进行比较。也就是本身要参与进来。
  • Comparator是一种工具。他规定那两个对象以一种规定的方式进行比较。本身是不参与比较的。参与比较的是传入的object对象。

参考博客:Java中的排序比较方式:自然排序和比较器排序
                  Comparable接口和Comparator接口

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×