美文网首页Java 核心技术
JAVA中的两个对比:Comparable & compareT

JAVA中的两个对比:Comparable & compareT

作者: cbw100 | 来源:发表于2020-02-19 10:29 被阅读0次

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

    1. 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
        }
    }
    
    

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

    2. Comparator接口定义

    public interface Comparator<T>
    
    

    此接口定义了很多方法:

    20180823153455315.png

    先看第一个: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 style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); box-sizing: border-box; margin: 0px; padding: 0px;">,Comparable <user style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); box-sizing: border-box; margin: 0px; padding: 0px;">两个接口后,我们的compareTo方法就可以写成这样:</user></user>

    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() 一模一样。

    推荐一下我的公众号: 【geekjc】,一起学习交流编程知识,分享经验,各种有趣的事,更多精彩内容,扫码进入小程序。

    tuiguang.png

    相关文章

      网友评论

        本文标题:JAVA中的两个对比:Comparable & compareT

        本文链接:https://www.haomeiwen.com/subject/kzwofhtx.html