你能說說Java中Comparable和Comparator的區別嗎

以前面試中被問到這個問題,當時不屑(會)回答,下來特地查了查,整理以下。java

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

 

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

 


Comparable

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

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

 

  • 比較者大於被比較者,返回正整數spa

  • 比較者等於被比較者,返回0code

  • 比較者小於被比較者,返回負整數對象

 

寫個很簡單的例子:blog

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,返回負整數

 

寫個很簡單的例子:

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接口的耦合性要強

  • 等等………..

相關文章
相關標籤/搜索