Java 中 Comparable 和 Comparator 的區別

聰明人有一個特色,就是善於把無價值的事作得有聲有色,在玻璃魚缸裏游泳,也有乘風破浪的氣魄。java

Java 中爲咱們提供了兩種比較機制:Comparable 和 Comparator,兩者都是用來實現對象的比較、排序。算法

下面分別對Comparable 和 Comparator作具體介紹並總結。dom


Comparable

Comparable能夠認爲是一個內比較器,實現了Comparable接口的類有一個特色,就是這些類是能夠和本身比較的,至於具體和另外一個實現了Comparable接口的類如何比較,則依賴compareTo方法的實現。this

若是add進入一個Collection的對象想要Collections的sort方法幫你自動進行排序的話,那麼這個對象必須實現Comparable接口。compareTo方法的返回值是int,有三種狀況:code

  • 比較者大於被比較者,返回正整數
  • 比較者等於被比較者,返回0
  • 比較者小於被比較者,返回負整數

寫個很簡單的例子:對象

public class Domain implements Comparable<Domain> {
    private String str;

    public Domain(String str) {
        this.str = str;
    }

    public int compareTo(Domain domain) {
        if (this.str.compareTo(domain.str) > 0)
            return 1;
        else if (this.str.compareTo(domain.str) == 0)
            return 0;
        else
            return -1;
    }

    public String getStr() {
        return str;
    }
}

public static void main(String[] args) {
    Domain d1 = new Domain("c");
    Domain d2 = new Domain("c");
    Domain d3 = new Domain("b");
    Domain d4 = new Domain("d");
    System.out.println(d1.compareTo(d2));
    System.out.println(d1.compareTo(d3));
    System.out.println(d1.compareTo(d4));
}

運行結果爲:排序

0
1
-1

注意一下,前面說實現Comparable接口的類是能夠支持和本身比較的,可是其實代碼裏面Comparable的泛型未必就必定要是Domain,將泛型指定爲String或者指定爲其餘任何任何類型均可以,只要開發者指定了具體的比較算法就行。接口


Comparator

Comparator接口裏面有一個compare方法,方法有兩個參數T o1和T o2,是泛型的表示方式,分別表示待比較的兩個對象,方法返回值和Comparable接口同樣是int,有三種狀況:開發

  • o1大於o2,返回正整數
  • o1等於o2,返回0
  • o1小於o3,返回負整數

寫個很簡單的例子:get

public class DomainComparator implements Comparator<Domain> {
    public int compare(Domain domain1, Domain domain2) {
        if (domain1.getStr().compareTo(domain2.getStr()) > 0)
            return 1;
        else if (domain1.getStr().compareTo(domain2.getStr()) == 0)
            return 0;
        else
            return -1;
    }
}

public static void main(String[] args) {
    Domain d1 = new Domain("c");
    Domain d2 = new Domain("c");
    Domain d3 = new Domain("b");
    Domain d4 = new Domain("d");
    DomainComparator dc = new DomainComparator();
    System.out.println(dc.compare(d1, d2));
    System.out.println(dc.compare(d1, d3));
    System.out.println(dc.compare(d1, d4));
}

看一下運行結果:

0
1
-1

由於泛型指定死了,因此實現Comparator接口的實現類只能是兩個相同的對象(不能一個Domain、一個String)進行比較了,實現Comparator接口的實現類通常都會以"待比較的實體類+Comparator"來命名

總結

若是實現類沒有實現Comparable接口,又想對兩個類進行比較(或者實現類實現了Comparable接口,可是對compareTo方法內的比較算法不滿意),那麼能夠實現Comparator接口,自定義一個比較器,寫比較算法。

實現Comparable接口的方式比實現Comparator接口的耦合性要強一些,若是要修改比較算法,要修改Comparable接口的實現類,而實現Comparator的類是在外部進行比較的,不須要對實現類有任何修改。所以:

  • 對於一些普通的數據類型(好比 String, Integer, Double…),它們默認實現了Comparable 接口,實現了 compareTo 方法,咱們能夠直接使用。
  • 而對於一些自定義類,它們可能在不一樣狀況下須要實現不一樣的比較策略,咱們能夠新建立 Comparator 接口,而後使用特定的 Comparator 實現進行比較。

不一樣之處:

我的感受說出上文觀點,這個提問就算回答完了,若是非要說不一樣之處,那就是:

  • Comparator位於java.util包下,而Comparable位於java.lang包下
  • 實現Comparable接口的方式比實現Comparator接口的耦合性要強
  • 等等………..
相關文章
相關標籤/搜索