天天看點

Comparable和Comparator的差別一、問題引入二、Comparable接口三、Comparator比較器四、總結

一、問題引入

使用集合工具類Collections的sort方法對集合内部元素排序,當存儲Integer類型資料時,程式的編譯、運作均正常,但當集合存儲自定義類型時,編譯器報錯,顯示未實作Comparable接口,如圖所示:

Comparable和Comparator的差別一、問題引入二、Comparable接口三、Comparator比較器四、總結
Comparable和Comparator的差別一、問題引入二、Comparable接口三、Comparator比較器四、總結

自定義類型 Person:

package cn.GTMStudio.Comparator;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

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

那麼這個Comparable是什麼呢?

二、Comparable接口

  • Comparable 在 java.lang 包下,是一個接口,内部隻有一個方法 compareTo():
public interface Comparable<T> {
    public int compareTo(T o);
}
           
  • public interface Comparable<> 此接口強行對實作它的每個類的對象進行整體排序。這種排序被稱為類的自然排序,類的compareTo方法被稱為它的自然比較方法。
  • 實作此接口的對象清單(和數組)可以通過 Collections.sort(和 Arrays.sort)進行自動排序。實作此接口的對象可以用作有序映射中的鍵或有序集合中的元素,無需指定比較器。
  • Comparable的排序規則:this-參數為升序,反之則為降序。

觀察一下Integer的源碼發現integer實作了Comparable接口,并重寫了compareTo接口

Comparable和Comparator的差別一、問題引入二、Comparable接口三、Comparator比較器四、總結
Comparable和Comparator的差別一、問題引入二、Comparable接口三、Comparator比較器四、總結

實作Comparable接口

package cn.GTMStudio.Comparator;

public class Person implements Comparable<Person>{
    private String name;
    private int age;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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



    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
	//重寫Comparable接口的方法
    @Override
    public int compareTo(Person o) {
        //Comparable排序規則:this-參數為升序,反之則為降序
        return this.age-o.age;
    }
}
           

再次運作程式,結果顯示正常,集合元素升序列印

Comparable和Comparator的差別一、問題引入二、Comparable接口三、Comparator比較器四、總結

三、Comparator比較器

試想這樣一種情況,某個自定義類型沒有實作Comparable接口,同時你無法修改該自定義類型,但是你必須要對集合元素進行排序,此時該怎麼辦呢?可以使用Comparator接口,該接口也稱為比較器。

  • 從上面内容可知使用自然排序需要類實作 Comparable,并且在内部重寫 comparaTo 方法。
  • Comparator 則是在外部制定排序規則,然後作為排序政策參數傳遞給某些類,比如 Collections.sort(), Arrays.sort(), 或者一些内部有序的集合(比如 SortedSet,SortedMap 等)。
  • 使用方式主要分三步:
    1. 建立一個 Comparator 接口的實作類,并指派給一個對象
    2. 在 compare 方法中針對自定義類寫排序規則
    3. 将 Comparator 對象作為參數傳遞給 排序類的某個方法,向排序類中添加 compare 方法中使用的自定義類

    建立Stdent類

package cn.GTMStudio.Comparator;

public class Student {
   private String name;
   private int id;

   public Student() {
   }

   public Student(String name, int id) {
       this.name = name;
       this.id = id;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getId() {
       return id;
   }

   public void setId(int id) {
       this.id = id;
   }

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

實作Comparator接口,定制外部排序規則

Collections.sort(list, new Comparator<Student>() {
           @Override
           public int compare(Student o1, Student o2) {
               //按學号升序排列
               int result = o1.getId() - o2.getId();
               if (result==0){
                   //如果學号相同,則按名字首字母降序排列
                   result=o2.getName().charAt(0)-o1.getName().charAt(0);
               }
               return result;
           }
       });
           

運作結果

Comparable和Comparator的差別一、問題引入二、Comparable接口三、Comparator比較器四、總結

四、總結

Java 中的兩種排序方式:

  • Comparable 自然排序。(實體類實作)
  • Comparator 是定制排序。(無法修改實體類時,直接在調用方建立)
  • 同時存在時采用 Comparator(定制排序)的規則進行比較

對于一些普通的資料類型(比如 String, Integer, Double…),它們預設實作了Comparable 接口,實作了 compareTo 方法,我們可以直接使用。

而對于一些自定義類,它們可能在不同情況下需要實作不同的比較政策,我們可以新建立 Comparator 接口,然後使用特定的 Comparator 實作進行比較。