java 使用Comparable接口实现自定义比较

最近写水题,很多都是要实现:按A字段降序排序,若相同则按B字段升序排序。利用JAVA的Comparable接口可以很轻易的实现。很多博客在写重写compareTo方法时,都只是说 "大于返回1 小于返回-1 相等返回0",这样的描述看得让人不知所云,自己亲自实践后,发现这些博客写的都有瑕疵,于是自己写下这篇博客,以后方便查阅。可能有些人没基础,所以我会从简单的讲起。

1、使用哪个方法实现排序?

在JAVA中可以通过下面两种自带方法实现排序 :

 //对数组排序
 Arrays.sort(待排序数组)
 //对列表排序
 Collections.sort(待排序列表);

 实际上我们查看Collections.sort()的源码可以发现,它也是复用了Arrays.sort()函数(毕竟数组列表可以相互转化):

default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray(); //先转化为数组
        Arrays.sort(a, (Comparator) c); //再排序
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }

 

2、对要排序的对象数组/列表里的对象要有什么要求?

想要排序,必须要先实现Comparable接口,并重写compareTo方法。可以查看Arrays.sort()的源码,其就是通用将对像转换成Comparable,再利用compareTo 函数来判断对象排序的先后顺序。

class Test implements Comparable<Test>{
    @Override
    public int compareTo(Test another) {
       ......
    }
}

 

3、如何自定义升/降序?

通过实现compareTo方法,我们可以比较灵活的定制按某某字段升序或降序,甚至可以实现按A降序,A相同时,按B升序的需求。显然,compareTo返回的是个int值,且在源码中,Arrays.sort()使用compareTo函数,只关心其符号:

1、小于0      2、大于0     3、等于0

在接下来的代码里,小于0用-1表示,大于0用1表示。

如何定义返回值?要看你是升序还是降序:

  • 升序排序
    大于 another对象 返回1
    小于 another对象 返回-1
    等于another对象 返回0
  • 降序排序
    大于 another对象 返回-1
    小于 another对象 返回1
    等于another对象 返回0

举例:现有Test类,其含有(int)score、(String)name两个字段,现要求按score降序排序若score相等,则按name升序排序。

class Test implements Comparable<Test>{
    int score;
    String name;

    public Test(int score, String name) {
        this.score = score;
        this.name = name;
    }

    @Override
    public int compareTo(Test another) {
        //score按降序
        if (this.score > another.score){
            return -1;
        }else if (this.score < another.score){
            return 1;
        }else {//成绩相等
            //按名字升序
            if (this.name.compareTo(another.name) > 0){
                return 1;
            }else if (this.name.compareTo(another.name) < 0){
                return -1;
            }else {//名字相等
                return 1;
            }
        }
    }

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

测试:

public static void main(String[] args) {
        Test[] tests = new Test[]{new Test(100,"b"),new Test(100,"a"),new Test(95,"c")};
        Arrays.sort(tests);
        for (int i = 0; i < tests.length; i++) {
            System.out.println(tests[i]);
        }
}

//测试结果
Test{score=100, name='a'}
Test{score=100, name='b'}
Test{score=95, name='c'}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章