Comparable和Comparator的區別

初次碰到這個問題是以前有一次電話面試,問了一個小時的問題,其中有一個問題就問到Comparable和Comparator的區別,當時沒答出 來。以後是公司入職時候作的一套Java編程題,裏面用JUnit跑用例的時候也用到了Comparator接口,再加上JDK的大量的類包括常見的 String、Byte、Char、Date等都實現了Comparable接口,所以要學習一下這兩個類的區別以及用法。面試

 

Comparable算法

Comparable能夠認爲是一個內比較器,實現了Comparable接口的類有一個特色,就是這些類是能夠和本身比較的,至於具體和另外一個實現了Comparable接口的類如何比較,則依賴compareTo方法的實現,compareTo方法也被稱爲天然比較方法。若是開發者add進入一個Collection的對象想要Collections的sort方法幫你自動進行排序的話,那麼這個對象必須實現Comparable接口。compareTo方法的返回值是int,有三種狀況:編程

一、比較者大於被比較者(也就是compareTo方法裏面的對象),那麼返回正整數dom

二、比較者等於被比較者,那麼返回0學習

三、比較者小於被比較者,那麼返回負整數this

寫個很簡單的例子:對象

 

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能夠認爲是是一個外比較器,我的認爲有兩種狀況可使用實現Comparator接口的方式:

一、一個對象不支持本身和本身比較(沒有實現Comparable接口),可是又想對兩個對象進行比較

二、一個對象實現了Comparable接口,可是開發者認爲compareTo方法中的比較方式並非本身想要的那種比較方式

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

一、o1大於o2,返回正整數

二、o1等於o2,返回0

三、o1小於o3,返回負整數

寫個很簡單的例子,上面代碼的Domain不變(假設這就是第2種場景,我對這個compareTo算法實現不滿意,要本身寫實現):

 

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和Comparator,後者相比前者有以下優勢:

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

二、實現Comparable接口的方式比實現Comparator接口的耦合性 要強一些,若是要修改比較算法,要修改Comparable接口的實現類,而實現Comparator的類是在外部進行比較的,不須要對實現類有任何修 改。從這個角度說,其實有些不太好,尤爲在咱們將實現類的.class文件打成一個.jar文件提供給開發者使用的時候。實際上實現Comparator 接口的方式後面會寫到就是一種典型的策略模式

固然,這不是鼓勵用Comparator,意思是開發者仍是要在具體場景下選擇最合適的那種比較器而已。

相關文章
相關標籤/搜索