JAVA中的两个对比:Comparable & compareTo & Comparator & compare

JAVA中的两个对比:Comparable & compareTo & Comparator & compare

java中的对比相关的几个接口长的还都挺像,搞不好就容易搞忘了是哪个了。所以抽出时间来看看他的源码,梳理梳理这2个接口,一方面是个总结,同时也方便记忆。
Comparable,顾名思义就是说能不能比,你去实现他就能比了,就Comparable了。
Comparator,顾名思义比较器,拿来比较的。

Comparable接口定义

java.lang.Comparable<T>

此接口只有一个方法就是public int compareTo(T o); 比较方法。compareTo方法返回int型的负数、0、正数,分别代表小于、等于、大于指定的对象。对于想要进行比较/排序的类,可以实现Comparable接口,实现Comparable接口一定要重写compareTo方法。例如:

public class User implements Comparable<User>{  
    private String name;
    private Integer age;

    // 省略 get set 方法 和构造方法

    @Override
    public int compareTo(User o) {
        return this.age.compareTo(o.age);
    }

    public static void main(String[] args) {
        User u1 = new User("李白", 20);
        User u2 = new User("杜甫", 40);
        System.out.println(u1.compareTo(u2)); // 输出 -1
    }
}

如上所见,使用和理解都很简单。

Comparator接口定义

public interface Comparator<T>

此接口定义了很多方法:
这里写图片描述

先看第一个:int compare(T o1, T o2); ,实现上面的compareTo相同的功能,如下:
import java.util.Comparator;

public class User implements Comparator<User>{
    private String name;
    private Integer age;

    // 省略 get set 方法 和构造方法

    @Override
    public int compare(User o1, User o2) {
        return (o1.getAge() < o2.getAge()) ? -1 : ((o1.getAge() > o2.getAge()) ? 1 : 0);
    }

    public static void main(String[] args) {
        User u1 = new User("李白", 20);
        User u2 = new User("杜甫", 40);
        System.out.println(u1.compare(u1, u2)); // 输出 -1
    }
}

对比上面的个compareTo方法后可以看出来,2个方法本质上并无太大差别。实际上他们的区别就是compareTo方法的实现是jdk已经实现过的,而compare则需要自己手动实现。

举个栗子:
我们的User类同时实现Comparator<User>,Comparable<User> 两个接口后,我们的compareTo方法就可以写成这样:

public class User implements Comparator<User>, Serializable,Comparable<User> {
    private String name;
    private Integer age;

    // 省略 get set 方法 和构造方法

    @Override
    public int compare(User o1, User o2) {
        return (o1.getAge() < o2.getAge()) ? -1 : ((o1.getAge() > o2.getAge()) ? 1 : 0);
    }

    @Override
    public int compareTo(User o) {
        return this.compare(this, o);
    }

    public static void main(String[] args) {
        User u1 = new User("李白", 20);
        User u2 = new User("杜甫", 40);
        System.out.println(u1.compareTo(u2)); // 输出 -1
    }
}

或者:

public class User implements Comparator<User>, Serializable,Comparable<User> {
    private String name;
    private Integer age;

    // 省略 get set 方法 和构造方法

    @Override
    public int compare(User o1, User o2) {
        return (o1.getAge() < o2.getAge()) ? -1 : ((o1.getAge() > o2.getAge()) ? 1 : 0);
    }

    @Override
    public int compare(User o1, User o2) {
        return  o1.compareTo(o2);
    }

    @Override
    public int compareTo(User o) {
        return this.age.compareTo(o.age);
    }

    public static void main(String[] args) {
        User u1 = new User("李白", 20, true);
        User u2 = new User("杜甫", 40, true);
        System.out.println(u1.compare(u1,u2)); // 输出 -1
    }
}

2种实现方式可以相互调用,不过总要有一个方法去写实现,如果2个方法相互调用且都不写实现的话,那就呵呵了,最终就是相互调用到死,StackOverflow了。

然后是第二个方法:
 default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

这个方法有点意思,方法上的注释是:Returns a comparator that imposes the reverse ordering of this comparator. 意思就是把刚刚实现的排序倒过来一下。实现如下:

    // User类与上面的User一样,实现了Comparator接口
    public static void main(String[] args) {
        User u1 = new User("李白", 20, true);
        User u2 = new User("杜甫", 40, true);
        System.out.println(u1.compare(u1,u2)); // 输出 -1

        Comparator<User> reversed = u1.reversed();
        System.out.println(reversed.compare(u1, u2)); // 输出 1
    }

这个方法有点意思是有点意思,不过看他的定义就知道:default 方法,说明此方法是java8后面加的,所以要注意java的环境。

然后是第三个方法:
    default Comparator<T> thenComparing(Comparator<? super T> other) {
        Objects.requireNonNull(other);
        return (Comparator<T> & Serializable) (c1, c2) -> {
            int res = compare(c1, c2);
            return (res != 0) ? res : other.compare(c1, c2);
        };
    }

看方法字面意思就知道,比一次后再比一次,就拿刚刚的方法来验证:

    public static void main(String[] args) {
        User u1 = new User("李白", 20, true);
        User u2 = new User("杜甫", 40, true);
        System.out.println(u1.compare(u1,u2)); // 输出 -1

        Comparator<User> reversed = u1.reversed();
        System.out.println(reversed.compare(u1, u2)); // 输出 1

        // 定义一个对比之后再对比的Comparator,此处就用上面的倒序的那个Comparator
        Comparator<User> thenComparing = u1.thenComparing(u1.reversed());
        // 所以两次倒序后,负负得正,又是输出-1
        System.out.println(thenComparing.compare(u1, u2)); // 输出 -1
    }
后面的几个thenComparingIntthenComparingLong 与这个差不多。

再下面的几个都是static方法:
 public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
        return Collections.reverseOrder();
    }

看方法的实现,与上面的default方法reversed() 一模一样。

猜你喜欢

转载自blog.csdn.net/u012843361/article/details/81981879