1. 程式人生 > >):Comparable介面和Comparator介面

):Comparable介面和Comparator介面

目錄

1 介紹

2 Comparable介面

3 Comparator介面

4 總結

1 介紹

      有這樣2個人,一個人光頭,一個人有黑色頭髮,現在不允許染髮,只允許光頭的帶假髮,理由是有頭髮的人沒有必要再帶假髮,那麼誰可以有多種顏色的頭髮?在這種情況下,有頭髮的人,因為他的頭髮和自身繫結在一起,是無法在換頭髮的;而光頭的頭髮(假髮套)和其自身是不繫結的,可以根據自己喜歡換不同顏色的髮套。有頭髮的人叫Comparable,光頭不是孟飛,也不是樂嘉,叫Comparator。

    Comparable和Comparator是java中2個比較介面。Comparable是和具體類繫結的,我們稱為“靜態繫結”(如上圖中有頭髮的人,頭髮是Comparable,頭是具體的類)。而對於Comparator,具體的類在需要是可選擇不同的Comparator繫結,是“動態繫結”(

策略模式)(如上圖中光頭的人,假髮是Comparator,頭是具體的類,可根據需要選擇不同的假髮)。兩者相比,Comparator比Comparable靈活,而且具體類可以在需要時選擇不同的Comparator。

2 Comparable介面

    java.lang. Comparable介面定義類的自然順序,實現該介面的類就可以按這種方式排序。Comparable只包含一個方法:

  1. publicinterface Comparable<T> {   
  2.     publicint compareTo(T o);   
  3. }   
int compareTo(Object o): 比較當前例項物件與物件o,如果位於物件o之前,返回負值,如果兩個物件在排序中位置相同,則返回0,如果位於物件o後面,則返回正值。String類實現了Comparable介面。     需要比較或排序的物件,可以選擇實現Comparable介面,自定義比較演算法。 例子
  1. import
     java.util.Arrays;  
  2. /**  
  3.  * @version 1.0 
  4.  * @date    2012-11-15 下午2:25:27  
  5.  * @fuction  實現Comparable介面 (先按序號比較,序號相等在比較姓名) */
  6.     publicclass Student implements Comparable  
  7.     {  
  8.         //學號
  9.         int num;  
  10.         //姓名
  11.         String name;  
  12.         //constructor
  13.         public Student(int num,String name)  
  14.         {  
  15.             this.num=num;  
  16.             this.name=name;  
  17.         }  
  18.         //重寫java.lang中的介面Comparable的方法compareTo,定製比較的規則.但必須遵守比較規則(比較結果大返回正數,相等返回0,小返回負數)
  19.         publicint compareTo(Object o) {  
  20.             Student s=(Student)o;  
  21.             int result=num>s.num ? 1:(num==s.num ? 0: -1);  
  22.             //學號相等時,按名字排序
  23.             if(0==result)  
  24.             {  
  25.                 //利用String的compareTo方法進行字元的比較
  26.                 result=name.compareTo(s.name);  
  27.             }  
  28.             return result;  
  29.         }  
  30.         @Override
  31.         public String toString() {  
  32.             return"Student [num=" + num + ", name=" + name + "]";  
  33.         }  
  34.     /** 
  35.      * @param args 
  36.      */
  37.     publicstaticvoid main(String[] args) {  
  38.         Student[] test=new Student[]{new Student(2"wangwu"),  
  39.                                      new Student(1"lisi"),  
  40.                                      new Student(1"goudan") };  
  41.         //排序
  42.         Arrays.sort(test);  
  43.         //列印
  44.         for(int i=0;i<test.length;i++)  
  45.         {  
  46.             System.out.println(test[i]);  
  47.         }  
  48.         //搜尋姓名為“wangwu”的學生   
  49.         int index=Arrays.binarySearch(test,new Student(2,"wangwu"));   
  50.         System.out.println("查詢的學生在陣列中的位置:"+index);     
  51.     }  
  52. }  

3 Comparator介面

 java.util.Comparator介面只包含2個方法

  1. int compare(T o1, T o2);  
  1. boolean equals(Object obj);  

int compare(T o1, T o2);比較用來排序的兩個引數。 

boolean equals(Object obj);指示是否其他物件“等於”此 Comparator。

實現了compare介面的類具體的實現是在compare方法中自定義比較演算法,然後將Comparator物件(實現了java.util.Comparator介面的物件)作為一個引數傳遞給欲比較或排序物件collection的某些排序方法。某些排序方法指的是能夠接受java.util.Comparator引數的方法,比如:java.util. Arrays的public static void sort(Object[] a, Comparator c)和Collections的sort方法。

例子

  1. import java.util.Arrays;  
  2. import java.util.Comparator;  
  3. /** 
  4.  * @version 1.0 
  5.  * @date 2012-11-15 下午11:21:09 
  6.  * @fuction 實現Comparator介面的比較演算法 
  7.  *按學號排序 先按學號排序,學號相等時,按姓名排序 o1>o2返回1,o1=o2返回0,o1>o2返回-1 
  8.  */
  9. publicclass ByNumComparator implements Comparator {  
  10.     publicint compare(Object o1, Object o2) {  
  11.         Student s1 = (Student) o1;  
  12.         Student s2 = (Student) o2;  
  13.         // 按學號排序
  14.         int result = s1.num > s2.num ? 1 : (s1.num == s2.num ? 0 : -1);  
  15.         // 學號相等時,按名字排序
  16.         if (result == 0) {  
  17.             int copmpareName=s1.name.compareTo(s2.name);  
  18.         //利用String的compareTo方法進行字元的比較  
  19.            if(copmpareName>0)  
  20.             result=1;  
  21.            elseif (copmpareName==0)  
  22.             result=0;  
  23.            else
  24.             result=-1;  
  25.         }  
  26.         return result;  
  27.     }  
  28.     publicstaticvoid main(String[] args) {  
  29.         Student[] test = new Student[] { new Student(2"wangwu"),  
  30.                 new Student(1"lisi"), new Student(1"goudan") };  
  31.         // 排序
  32.         Arrays.sort(test, new ByNumComparator());  
  33.         // 列印
  34.         System.out.println("排序之後");  
  35.         for (int i = 0; i < test.length; i++) {  
  36.             System.out.println(test[i]);  
  37.         }  
  38.     }  
  39. }  


輸出結果:

排序之後
Student [num=1, name=goudan]
Student [num=1, name=lisi]
Student [num=2, name=wangwu]

4 總結

       一般在對物件進行比較或排序時,需要物件實現Comparable介面或者在使用排序方法(比如Arrays的sort)方法時,傳入實現了Comparator介面的類的物件。

分類: J2SE 1655人閱讀 評論(4) 收藏 舉報

 Comparable & Comparator 都是用來實現集合中元素的比較、排序的,只是 Comparable 是在集合內部定義的方法實現的排序,Comparator 是在集合外部實現的排序,所以,如想實現排序,就需要在集合外定義 Comparator 介面的方法或在集合內實現 Comparable 介面的方法。

Comparator位於包java.util下,而Comparable位於包   java.lang下

Comparable 是一個物件本身就已經支援自比較所需要實現的介面(如 String、Integer 自己就可以完成比較大小操作,已經實現了Comparable介面)   

 自定義的類要在加入list容器中後能夠排序,可以實現Comparable介面,在用Collections類的sort方法排序時,如果不指定Comparator,那麼就以自然順序排序,如API所說:
Sorts the specified list into ascending order, according to the natural ordering of its elements. All elements in the list must implement the Comparable interface
這裡的自然順序就是實現Comparable介面設定的排序方式。

而 Comparator 是一個專用的比較器,當這個物件不支援自比較或者自比較函式不能滿足你的要求時,你可以寫一個比較器來完成兩個物件之間大小的比較。
  
可以說一個是自已完成比較,一個是外部程式實現比較的差別而已。

用 Comparator 是策略模式(strategy design pattern),就是不改變物件自身,而用一個策略物件(strategy object)來改變它的行為。
  
比如:你想對整數採用絕對值大小來排序,Integer 是不符合要求的,你不需要去修改 Integer 類(實際上你也不能這麼做)去改變它的排序行為,只要使用一個實現了 Comparator 介面的物件來實現控制它的排序就行了。


// AbsComparator.java     
import   java.util.*;

public   class   AbsComparator   implements   Comparator   {     
    public   int   compare(Object   o1,   Object   o2)   {     
      int   v1   =   Math.abs(((Integer)o1).intValue());     
      int   v2   =   Math.abs(((Integer)o2).intValue());     
      return   v1   >   v2   ?   1   :   (v1   ==   v2   ?   0   :   -1);     
    }     
}

    
可以用下面這個類測試 AbsComparator:     

// Test.java     
import   java.util.*;     

public   class   Test   {     
    public   static   void   main(String[]   args)   {     
    
      //產生一個20個隨機整數的陣列(有正有負)     
      Random   rnd   =   new   Random();     
      Integer[]   integers   =   new   Integer[20];     
      for(int   i   =   0;   i   <   integers.length;   i++)     
      integers[i]   =   new   Integer(rnd.nextInt(100)   *   (rnd.nextBoolean()   ?   1   :   -1));     
    
      System.out.println("用Integer內建方法排序:");     
      Arrays.sort(integers);     
      System.out.println(Arrays.asList(integers));     
    
      System.out.println("用AbsComparator排序:");     
      Arrays.sort(integers,   new   AbsComparator());     
      System.out.println(Arrays.asList(integers));     
    }     
}



 Collections.sort((List<T> list, Comparator<? super T> c)是用來對list排序的。


如果不是呼叫sort方法,相要直接比較兩個物件的大小,如下:
Comparator定義了倆個方法,分別是   int   compare(T   o1,   T   o2)和   boolean   equals(Object   obj),
用於比較兩個Comparator是否相等
true only if the specified object is also a comparator and it imposes the same ordering as this comparator.
有時在實現Comparator介面時,並沒有實現equals方法,可程式並沒有報錯,原因是實現該介面的類也是Object類的子類,而Object類已經實現了equals方法

 Comparable介面只提供了   int   compareTo(T   o)方法,也就是說假如我定義了一個Person類,這個類實現了   Comparable介面,那麼當我例項化Person類的person1後,我想比較person1和一個現有的Person物件person2的大小時,我就可以這樣來呼叫:person1.comparTo(person2),通過返回值就可以判斷了;而此時如果你定義了一個   PersonComparator(實現了Comparator介面)的話,那你就可以這樣:PersonComparator   comparator=   new   PersonComparator();
comparator.compare(person1,person2);。