walterwing |
|
|||
日歷
統計
導航常用鏈接留言簿(1)隨筆分類隨筆檔案搜索最新評論
閱讀排行榜評論排行榜 |
前面介紹完了幾個Collections Framework的幾個主要接口,下面來講一下對象是如何排序的,為下面的SortedSet和SortedMap做準備。
舉個例子,我們有個list,里面存儲了若干個String,那么我們可以用下面的方法來對list內部的String按照字母順序來排序: Collections.sort(list);
那如果list里存放的不是String,而是其他類型的對象呢?能否排序就取決于該對象是否實現了Comparable這個接口,如果沒有的話,Collections.sort()方法就將拋出ClassCastExcepton。 下面的表格列出了java里實現了Comparable接口的一些重要的類:
如果你想對自己的類實現Comparable接口,一定要先參考API文檔關于Comparable接口的說明。 另外,如果你想用自己的排序屏蔽原本的排序方式,又或者你想對某個類的對象排序,但該類并沒有實現Comparable接口,這個時候,你就可以用Comparator接口來實現你自己的排序方式。 但有一點要注意,排序也不是亂排的,應該盡量和類方法中的equals方法保持一致,尤其是當Comparator用在SortedSet或者SortedMap中的時候(這兩個可以通過指定Comparator來覆蓋自然排序方式)。 舉個例子來說: public class Cmp {
/** * @param args */ public static void main(String[] args) { SortedSet set = new TreeSet(); set.add("a"); set.add("a"); Iterator it = set.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } } 我們知道Set是不允許有重復元素的,所以即使我們加入了兩個“a”,最后輸出的結果仍然是只有一個“a”。 但如果我們對程序做如下修改,指定自己的Comparator: public class Cmp {
static final Comparator cp = new Comparator() { public int compare(Object o1, Object o2) { return 1; } }; /** * @param args */ public static void main(String[] args) { SortedSet set = new TreeSet(cp); set.add("a"); set.add("a"); Iterator it = set.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } } 這次輸出的結果將是兩個"a",這與Set本身的規范并不相符。 6. SortedSet SortedSet一種按升序來排列元素的Set。排序的規則是按照元素的自然順序,或是按照構造函數中指定的Comparator規定的順序。 下面是SortedSet的定義: public interface SortedSet<E> extends Set<E> {
// Range-view SortedSet<E> subSet(E fromElement, E toElement); SortedSet<E> headSet(E toElement); SortedSet<E> tailSet(E fromElement); // Endpoints E first(); E last(); // Comparator access Comparator<? super E> comparator(); } 我們看到,SortedSet提供了一些特殊的操作:
·SortedSet得到的iterator是按順序進行遍歷的(Set沒有順序) ·toArray得到的數組是按序排列SortedSet中的元素的(Set沒有順序) 所有通用有序 set 實現類都應該提供 4 個“標準”構造方法: 1) void(無參數)構造方法,它創建一個空的有序 set,按照元素的自然順序進行排序。 2) 帶有一個 Comparator 類型參數的構造方法,它創建一個空的有序 set,根據指定的比較器進行排序。 3) 帶有一個 Collection 類型參數的構造方法,它創建一個新的有序 set,其元素與參數相同,按照元素的自然順序進行排序。 4) 帶有一個 SortedSet 類型參數的構造方法,它創建一個新的有序
set,其元素和排序方法與輸入的有序 set 相同。如何做到這一點?別忘了SortedSet本身就有一個comparator()方法,可以返回他所用的Comparator。但要注意的是無法保證強制實施此建議,因為接口不能包含構造方法。
在介紹List的時候,我們曾經強調,List里的range-view方法List<E> subList(int from, int to);是要嚴格避免濫用的。因為在subList的作用域范圍內,任何對list本身的修改都將使subList的行為不可預期。 但是在SortedSet里情況就不一樣了,你應該注意到,SortedSet里的三個range-view方法,都是根據提供的比較范圍來截取subSet,而不是像List里那樣使用索引。這樣在subSet的作用域范圍內,對set本身的修改都將反映到subSet上,反之亦然。參見下面的例子:
public class Cmp {
/** * @param args */ public static void main(String[] args) { // SortedSet set = new TreeSet(cp); SortedSet set = new TreeSet(); set.add("a"); set.add("b"); set.add("c"); set.add("d"); set.add("e"); SortedSet sub = set.tailSet("c"); Iterator it = sub.iterator(); while(it.hasNext()) { System.out.println(it.next()); } set.add("f"); System.out.println("-------------------"); it = sub.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } } 輸出的結果是: c
d e ------------------- c d e f 可以看到,我們得到“值大于等于c”的subSet后,當我們再向原來的set加入一個新的元素“f”,由于這個元素也大于“c”,那么這個元素也將反映到subSet上。 下面介紹一個比較特殊的小技巧:通過使用subSet,如何得到一個閉包的結果? 我們知道,如果按照一般的調用,下面的代碼是獲得大于等于“doorbell”而小于“pickle”的subSet: dictionary.subSet("doorbell", "pickle");
而我們可以通過下面方法得到大于等于“doorbell”而小于等于“pickle”的subSet: dictionary.subSet("doorbell", "pickle\0");
同理,我們可以通過下面方法得到大于“doorbell”而小于“pickle”的subSet: dictionary.subSet("doorbell\0", "pickle");
7. SortedMap SortedMap是對key進行升序排列的Map。 下面是其定義: public interface SortedMap<K, V> extends Map<K, V>{
Comparator<? super K> comparator(); SortedMap<K, V> subMap(K fromKey, K toKey); SortedMap<K, V> headMap(K toKey); SortedMap<K, V> tailMap(K fromKey); K firstKey(); K lastKey(); } 和SortedSet類似,SortedMap也提供了如下一些額外的操作:
·toArray得到的數組是按序排列SortedMap中的元素的(Map沒有順序) 注意,如果有序映射要正確實現 Map 接口,則有序映射所維持的順序(無論是否提供了明確的比較器)都必須與 equals 一致。(有關與 equals 一致 的精確定義,請參閱 Comparable 接口或 Comparator 接口)。這是因為 Map 接口是按照 equals 操作定義的,但有序映射使用它的 compareTo(或 compare)方法對所有鍵進行比較,因此從有序映射的角度來看,此方法認為相等的兩個鍵就是相等的。即使順序與 equals 不一致,樹映射的行為仍然是 定義良好的,只不過沒有遵守 Map 接口的常規協定。 所有通用有序映射實現類都應該提供 4 個“標準”構造方法:1) void(無參數)構造方法,它創建一個空的有序映射,按照鍵的自然順序進行排序。2) 帶有一個 Comparator 類型參數的構造方法,它創建一個空的有序映射,根據指定的比較器進行排序。3) 帶有一個 Map 類型參數的構造方法,它創建一個新的有序映射,其鍵-值映射關系與參數相同,按照鍵的自然順序進行排序。4) 帶有一個 SortedMap 類型參數的構造方法,它創建一個新的有序映射,其鍵-值映射關系和排序方法與輸入的有序映射相同。無法保證強制實施此建議,因為接口不能包含構造方法。
總結 The Java Collections Framework hierarchy consists of two distinct interface trees:
|
![]() |
|
Copyright © This is Wing | Powered by: 博客園 模板提供:滬江博客 |