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'}

 

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