java-comparable和comparator的區別

這兩個類都是接口,首先看看裏面的源碼:

package java.lang;
import java.util.*;
public interface Comparable<T> {
    public int compareTo(T o);
}
package java.util;

public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
}

上面分別是comparable和comparator的源碼,兩個都是接口,並且非常簡單,僅僅有一兩個方法。

下面看用法:
Comparable用法:

import java.util.Arrays;   
public class ComparableUser implements Comparable {  

    private String id;  
    private int age;  

    public ComparableUser(String id, int age) {  
        this.id = id;  
        this.age = age;  
    }  

    public int getAge() {  
        return age;  
    }  

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

    public String getId() {  
        return id;  
    }  

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

    public int compareTo(Object o) {  
        return this.age - ((ComparableUser) o).getAge();  
    }  

    /** 
     * 測試方法 
     */  
    public static void main(String[] args) {  
        ComparableUser[] users = new ComparableUser[] {  
                new ComparableUser("u1001", 25),  
                new ComparableUser("u1002", 20),  
                new ComparableUser("u1003", 21) };  
        Arrays.sort(users);  
        for (int i = 0; i < users.length; i++) {  
            ComparableUser user = users[i];  
            System.out.println(user.getId() + " " + user.getAge());  
        }  
    }  

}  

comparator用法:

public class User {  

    private String id;  
    private int age;  

    public User(String id, int age) {  
        this.id = id;  
        this.age = age;  
    }  

    public int getAge() {  
        return age;  
    }  

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

    public String getId() {  
        return id;  
    }  

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

import java.util.Arrays;  
import java.util.Comparator;  
public class UserComparator implements Comparator {  

    public int compare(Object arg0, Object arg1) {  
        return ((User) arg0).getAge() - ((User) arg1).getAge();  
    }  

    public static void main(String[] args) {  
        User[] users = new User[] { new User("u1001", 25),  
                new User("u1002", 20), new User("u1003", 21) };  
        Arrays.sort(users, new UserComparator());  
        for (int i = 0; i < users.length; i++) {  
            User user = users[i];  
            System.out.println(user.getId() + " " + user.getAge());  
        }  
    }  
} 

上面分別就是comparable和comparator兩個接口的用法。

理論部分:
Comparable & Comparator 都是用來實現集合中元素的比較、排序的,只是 Comparable 是在集合內部定義的方法實現的排序,Comparator 是在類外部實現的排序,所以,如想實現排序,就需要在類外定義 Comparator 接口的方法或在類內實現 Comparable 接口的方法。(這裏所說的類外,是值User類的類外。從上面的代碼可以很明顯的看出來,ComparableUser 類實現了comparable接口,comparable接口就是類內部實現,改變了類的結構。User類不實現比較功能,不能夠比較,但是通過類外定義比較器UserComparator 使其具備可比較功能。

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

Comparable 是一個對象本身就已經支持自比較所需要實現的接口(如 String、Integer 自己就可以完成比較大小操作,已經實現了Comparable接口)

自定義的類要在加入list容器中後能夠排序,可以實現Comparable接口,在用Collections類的sort方法排序時,如果不指定Comparator,那麼就以自然順序排序,這裏的自然順序就是實現Comparable接口設定的排序方式。

而 Comparator 是一個專用的比較器,當這個對象不支持自比較或者自比較函數不能滿足你的要求時,你可以寫一個比較器來完成兩個對象之間大小的比較。

因此,可以說上面的兩個接口,一個是自己完成比較,一個是類外部定義比較器實現比較的差別而已。

用 Comparator 是策略模式(strategy design pattern),就是不改變對象自身,而用一個策略對象(strategy object)來改變它的行爲。
這句話,我覺得說得很好!因爲Comparator 是比較器,並且是在類外定義的,可以多個類複用!相當於是一種策略,當然可以定義多個策略。如果是在類內部定義的比較功能,那類就不具備這種策略了。

有時在實現Comparator接口時,並沒有實現equals方法,可程序並沒有報錯,原因是實現該接口的類也是Object類的子類,而Object類已經實現了equals方法。
這一點也是需要注意的。按理論上講,當comparator的compare(T,T)方法返回0的時候,equals方法應當返回true表示兩個對象相等。

上面的ComparableUser 類實現了comparable接口,所以有下面的事實:
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);。

通過比較我們可以發現,兩個接口使用情況不同:
1、兩種方法各有優劣, 用Comparable 簡單, 只要實現Comparable 接口的對象直接就成爲一個可以比較的對象,但是需要修改源代碼
2、用Comparator 的好處是不需要修改源代碼, 而是另外實現一個比較器, 當某個自定義的對象需要作比較的時候,把比較器和對象一起傳遞過去就可以比大小了, 並且在Comparator 裏面用戶可以自己實現複雜的可以通用的邏輯,使其可以匹配一些比較簡單的對象,那樣就可以節省很多重複勞動了。
3、Comparator可以看成一種算法的實現,將算法和數據分離,Comparator也可以在下面兩種環境下使用:
3.1 類的設計師沒有考慮到比較問題而沒有實現Comparable,可以通過Comparator來實現排序而不必改變對象本身
3.2 可以使用多種排序標準,比如升序、降序等。

參考:
http://pengcqu.iteye.com/blog/490149
http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt159
http://blog.csdn.net/mageshuai/article/details/3849143

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章