所使用的jdk版本爲1.8版本,先看一下SortedMap在JDK中Map的UML類圖中的位置:
2.1.2 SortedMap接口
SortedMap<K,V>繼承Map<K,V>接口,是一個更進一步提供基於鍵key的總體排序的 Map。該映射是根據其鍵key的自然順序(自然排序的定義可以參見java.lang.Comparable接口,就是實現該接口)進行排序的,或者根據通常在創建有序映射SortedMap時提供的 Comparator 進行排序。
插入有序映射的所有鍵都必須實現Comparable接口(或者被指定的比較器Comparator接受)。另外,所有這些鍵都必須是可互相比較的:對有序映射中的任意兩個鍵k1和k2,執行k1.compareTo(k2)(或comparator.compare(k1, k2))都不得拋出ClassCastException。試圖違反此限制將導致有問題的的方法或者構造方法調用拋出ClassCastException。
SortedMap<K,V>接口從定義來看比較簡單,需要注意的就是其中的key要麼實現Comparable接口要麼被指定的比較器Comparator接受。接口定義描述建議所有的SortedMap實現類都應該提供四個標準的構造函數:
(1)void 無參的構造函數,此時按照鍵的自然順序進行排序;
(2)只有一個 Comparator 類型參數的構造方法,它創建一個空的有序映射,並且根據指定的 Comparator進行排序;
(3)只有一個 Map 類型參數的構造方法,它創建一個新的有序映射,其鍵-值映射關係與參數Map相同,按照鍵的自然順序進行排序;
(4)只有一個 SortedMap 類型參數的構造方法,它創建一個新的有序映射,其鍵-值映射關係和排序方法與入參的SortedMap相同。
因爲接口中無法定義構造方法,無法保證以上四種方法一定就會被實現。最上面的圖,SortedMap實現類TreeMap是全部實現了這四個構造方法的。
因爲SortedMap定義相對簡單,簡單列一些裏面的函數:
public interface SortedMap<K,V> extends Map<K,V> {
/**
* 返回對此映射中的鍵進行排序的比較器;如果使用的自然順序,返回null
*/
Comparator<? super K> comparator();
/**
* 返回此映射的部分視圖,其鍵值的範圍從 fromKey(包括)到 toKey(不包括)。(如果 fromKey
* 和 toKey 相等,則返回映射爲空。)返回的映射受此映射支持,所以在返回映射中的更改將反映在此
* 映射中,反之亦然。返回的映射支持此映射支持的所有可選映射操作。
* 如果試圖在返回映射的範圍之外插入鍵,則返回的映射將拋出 IllegalArgumentException。
*
* @param fromKey - 返回映射中key的低端點(包括)
* @param toKey - 返回映射中鍵的高端點(不包括)
* @return 此映射的部分視圖,其鍵值的範圍從 fromKey(包括)到 toKey(不包括)
* @throws ClassCastException - 如果無法使用此映射的比較器(如果此映射沒有比較器,則使用
* 自然順序)比較 fromKey 和 toKey。如果 fromKey 或 toKey 不能與映射中當前鍵進行比較,則
* 實現可以(但不是必須)拋出此異常。
* @throws NullPointerException - 如果 fromKey 或 toKey 爲 null,並且此映射不允許使
* 用 null 鍵
* @throws IllegalArgumentException - 如果 fromKey 大於 toKey;如果此映射本身有範圍限
* 制,並且 fromKey 或 toKey 位於範圍的邊界之外
*/
SortedMap<K,V> subMap(K fromKey, K toKey);
/**
* 返回此映射的部分視圖,其鍵值嚴格小於 toKey。返回的映射受此映射支持,所以在返回映射中的更改
* 將反映在映射中,反之亦然。返回的映射支持此映射支持的所有可選映射操作。
*
* 如果試圖在返回映射的範圍之外插入鍵,則返回的映射將拋出 IllegalArgumentException。
*
* @param toKey 返回映射視圖中鍵的高端點(不包括)
* @return 此映射的部分視圖,且其中的鍵嚴格小於 toKey
* @throws ClassCastException 如果 toKey 與此映射的比較器不兼容(或者,如果該映射沒有比
* 較器, 如果 toKey 沒有實現 Comparable)。如果 toKey 不能與映射中的當前鍵進行比較,則實
* 現可以(但不是必須)拋出此異常。
* @throws NullPointerException 如果toKey爲null,且該映射不允許key爲null
* @throws IllegalArgumentException 如果此映射本身有範圍限制,並且 toKey 位於範圍的邊界
* 之外
*/
SortedMap<K,V> headMap(K toKey);
/**
* 返回此映射的部分視圖,其鍵大於等於 fromKey。返回的映射受此映射支持,所以在返回映射中的更改
* 將反映在映射中,反之亦然。返回的映射支持此映射支持的所有可選映射操作。
* 如果試圖在返回映射的範圍之外插入鍵,則返回的映射將拋出 IllegalArgumentException。
*
* @param fromKey 返回映射中鍵的低端點(包括)
* @return 此映射的部分視圖,其中的鍵大於等於 fromKey
* @throws ClassCastException 如果 fromKey 與此映射的比較器不兼容(或者,如果該映射沒有
* 比較器;如果 fromKey 沒有實現 Comparable)。如果 fromKey 不能與映射中的當前鍵進行比
* 較,則實現可以(但不是必須)拋出此異常。
* @throws NullPointerException 如果 fromKey 爲 null,並且此映射不允許使用 null 鍵
* @throws IllegalArgumentException 如果此映射本身有範圍限制,並且 fromKey 位於範圍的
* 邊界之外
*/
SortedMap<K,V> tailMap(K fromKey);
/**
* 返回此映射中當前第一個(最低)鍵。
*
* @return 返回此映射中當前第一個(最低)鍵。
* @throws NoSuchElementException 如果map爲空(即size() == 0)
*/
K firstKey();
/**
* 返回映射中當前最後一個(最高)鍵。
*
* @return 返回映射中當前最後一個(最高)鍵。
* @throws NoSuchElementException 如果map爲空(即size() == 0)
*/
K lastKey();
/**
* 與父接口Map中的定義一樣,但有順序
*/
Set<K> keySet();
/**
* 與父接口Map中的定義一樣,但有順序(根據key的順序)
*/
Collection<V> values();
/**
* 與父接口Map中的定義一樣,但有順序(根據key的順序)
*/
Set<Map.Entry<K, V>> entrySet();
}
需要注意的地方:
1、subMap(K fromKey, K toKey)、headMap(K toKey)、tailMap(K fromKey),都是滿足fromKey <= key < toKey;
2、firstKey()和lastKey()方法,當SortedMap對象爲空(size() == 0)就會拋出NoSuchElementException異常;
3、subMap等子集map和當前sortedMap的元素變更是互相影響的。
以上注意點可以用TreeMap實現驗證(後續會分析在TreeMap中的實現):
public static void main(String[] args) {
SortedMap<Integer, Integer> sortedMap = new TreeMap();
sortedMap.put(2,2);
sortedMap.put(4,4);
sortedMap.put(1,1);
System.out.println(sortedMap.subMap(1,2));
System.out.println(sortedMap.headMap(2));
System.out.println(sortedMap.tailMap(2));
//獲取的子集中添加一個元素會影響當前sortedMap
SortedMap<Integer, Integer> subSortedMap = sortedMap.subMap(0,4);
subSortedMap.put(3,3);
//當前sortedMap增減元素會影響子集subSortedMap
sortedMap.put(0,0);
System.out.println(subSortedMap);
System.out.println(sortedMap);
}
程序輸出結果:
{1=1}
{1=1}
{2=2, 4=4}
{0=0, 1=1, 2=2, 3=3}
{0=0, 1=1, 2=2, 3=3, 4=4}
以上,SortedMap<K,V>暫時寫這麼多~
題外話:這裏發現一個值得玩味的地方,就是keySet()、values()、entrySet()三個方法在父接口Map已經有相同結構的方法定義了,在SortedMap中又重新定義了一次(不過返回的都是有順序的)。JDK中還有很多類似這樣子接口重新定義了父接口中方法情況,比如List接口中定義了和父接口Collection一樣的size()、isEmpty()等,感覺這種更多是處於軟件工程和設計模式等方面的考慮吧,不知諸位對此有何看法,歡迎留言賜教~