天天看點

java 中Comparable 和 Comparator比較

Comparable 和 Comparator比較

  • 兩者都 是接口
  • Comparable
    • 繼承了這個接口,實作接口的方法(自定義排序規則),就表示“該類支援排序”
    • 相當于“内部比較”
    • 如果某個類實作了這個接口,就可以通過 Arrasys.sort() 對該類的數組排序
    • 如果這個類裝在容器中(List,Set),就可以用Collections.sort()排序
  • Comparato
    • 是比較器的意思,器 相當于工具 ,某個類實作這個接口就可以有比較的規則
    • 相當于“外部比較”

a.Comparable 接口

例子**

/**
 * @author bigguy_hc
 * @create 2018-09-03 11:32
 */
public class Person implements Comparable<Person>{  // 實作接口,重寫方法
    int age;
    int score;

    public Person(){}

    public Person(int age,int score){
        this.age = age;
        this.score = score;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", score=" + score +
                '}';
    }

    @Override
    // 重寫方法,自定義排序規則,這裡表示按年齡排序,
    public int compareTo(com.bigguy.Person o) {     
        return this.getAge()-o.getAge();
    }
}
           

測試 Arrays.sort()

// 數組排序 
public void test2(){

        Person []pers ={new Person(,),new Person(,),new Person(,)};

 // 内部判斷的依據是實作了 Comparable 接口,排序規則是 Person 重寫compareTo()方法定義的規則

        Arrays.sort(pers);         
        for (Person per : pers) {
            System.out.println(per);
        }
    }
           

輸出

Person{age=, score=}
Person{age=, score=}
Person{age=, score=}
           

測試 Collections.sort()

public void test2(){

        Person []pers ={new Person(,),new Person(,),new Person(,)};

        List<Person> list = Arrays.asList(pers);

        Collections.sort(list);             // 内部的比較規則是内部原始的 compareTo()方法

        for (Person person : list) {
            System.out.println(person);
        }
    }
           

輸出

Person{age=, score=}
Person{age=, score=}
Person{age=, score=}
           

b.Comparator接口

如果就按照上面的代碼(person 實作了Comparable 接口并重寫了對應的方法)

此時,需求改變,現在需要通過 score 從大到小排序,不更改 person 原來代碼,就需要自定義比較器類

class PersonScoreComparator implements Comparator<Person>{
    public int compare(Person o1, Person o2) {
        return o2.getScore()-o1.getScore();
    }
}

 public void testComparator(){

     Person []pers ={new Person(,),new Person(,),new Person(,)};

     List<Person> list = Arrays.asList(pers);

     // 這裡傳入一個比較器,裡面自定義了排序規則
     Collections.sort(list,new PersonScoreComparator());

     for (Person person : list) {
         System.out.println(person);
     }
 }
/*輸出:
    Person{age=24, score=100}
    Person{age=23, score=91}
    Person{age=21, score=85}
*/
注意:
    至于什麼時候是升序,什麼時候是降序,就是重寫方法時的規則:

    public int compare(Person o1, Person o2) {
        return o2.getScore()-o1.getScore();     // 用 o2 - o1 的就是 大 -> 小
    }
           

c.總結

Comparator 的靈活性更高,不修改比較累的原代碼,可以自定義類并重寫方法,但是比較麻煩,

Comparable 簡單,靈活性差,如果需要改變,需要更改原代碼

d. Arrays.sort() 和 Collections.sort() 的 jdk 源碼

Arrays.sort()

public static void sort(Object[] a) {
    if (LegacyMergeSort.userRequested)
        legacyMergeSort(a);
    else
        ComparableTimSort.sort(a, , a.length, null, , );
}
           

Collections.sort() 沒有傳入比較器

public static <T extends Comparable<? super T>> void sort(List<T> list) {
     list.sort(null);       // 傳入 null 表示傳入的比較器為 null
 }

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);
    }
}

public static <T> void sort(T[] a, Comparator<? super T> c) {
    if (c == null) {        // 因為上面傳入 null ,是以走 sort(a)
        sort(a);
    } else {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, c);
        else
            TimSort.sort(a, , a.length, c, null, , );
    }
}
           

Collections.sort() 傳入比較器

public static <T> void sort(List<T> list, Comparator<? super T> c) {
     list.sort(c);
 }
// 這個方法其實是和上面方法時同一個方法,提高了代碼的複用性 
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);
    }
}
           

總結:

Arrays.sort() 和 Collections.sort() 先判斷是否傳入比較器

如果傳入比較器按比較器的規則比較

否則如果實作了Comparable 接口,按照重寫 的compareTo()方法規則比較

否則,如果還比較則報錯(裡面的元素沒有比較性)