java.util.Comparator接口容易被實現並使用,但是在Comparator的API文檔裡有些部分還是應當仔細閱讀一下的。
實現了Comparator接口的類可以傳給例如Collections.sort這樣的排序方法。它們也可以被Map或者Set類使用,用來保證Map或者Set裡的元素始終是按某種順序排列的。TreeSet和TreeMap就是這樣的類。
在Comparator接口裡,只有一個方法是需要實現的:
int compare(Object o1,Object o2);
如果o1小於o2,返回一個負數;如果o1大於o2,返回一個正數;如果他們相等,則返回0;
這些就是通常為了完成比較所要做的一切,但是在Comparator接口的契約裡還有別的義務。
首先,compare方法一定要是對稱的,意思是compare(a,b)返回的結果要跟compare(b,a)相反。相反的結果意味著,要麼返回的值帶有不同的正負號,要麼都是0。注意,象compare(a,b)返回4而compare(b,a)返回-2這樣的情況是合法的。方法裡常常可能拋出異常,在這個方法裡拋出異常也要是對稱的。如果調用compare(a,b)時拋出了一個ClassCastException異常,那麼調用compare(b,a)時也必須拋出一個ClassCastException異常。
考慮下面的代碼片斷:
public int compareTo(Object o1, Object o2) {
if(o1 instanceof Long) {
Long ln = (Long)o1;
return ln.compareTo(o2);
} else {
return 0;
}
}
如果a是new Long(5),b是”Text”,那麼執行compare(o1,o2)將在java.lang.Long的compareTo方法裡拋出一個ClassCastException,而執行compare(o2,o1)時將返回0(譯者注:原文這裡是compare(o1,o2),根據上下文,應該是compare(o2,o1))。
其次,任何你准備重用的Comparator都必須是可序列化的。TreeSet和TreeMap類存儲Comparator以便進行比較,因此為了這兩個類能被序列化,它們使用的Comparator也必須能被序列化。
第三,如果進行比較操作時,有多種比較方法,那麼Comparator應當實現equals方法。開發者創建有多種比較形式的Comparator是很常見的,例如:
import java.util.Comparator;
public class ExampleComparator {
private int type;
public ExampleComparator(int i) {
this.type = i;
}
public int compareTo(Object o1, Object o2) {
if(type == 1) {
// one type of comparison
....
} else
if(type == 2) {
// another form of comparison
....
}
}
}
Comparator接口,通常被Collections.sort方法使用,它是JAVA中需要了解的一個很重要的部分,因為它有一些重要的契約義務,而它們經常被忽略了。