之前學習的是Collection層次的List接口。List層次比較簡單,除去與多線程安全相關的CoppyOnWriteArrayList<T>類,這一個類在集中涉及多線程相關知識時候再學習,以及已經過時的向量Vector<T>、棧Stack<T>外,只剩下兩種比較常用的List接口的實現,也就是基於數組的ArrayList和基於鏈表的Linkedlist兩個類。這兩個列表實現中最簡單、最常用的還是ArrayList。至於LinkedList,由於其具體實現中實現了Deque隊列接口,在功能上具有比列表更多的功能,所以在學習完隊列之後再學習Linkedlist應該是比較合理的。
在平時的開發中由於隊列用到的比較少,所以關於隊列的學習也放置在後面。Collection中的另外一個常用的容器是Set接口的相關實現類。又由於java在設計Set實現類時是基於Map進行實現的,也就是說沒有Map就沒有Set,故而接下來先學習Map,然後再學習Set,這個學習順序應該是比較合理的。
下面先放上一張Map接口的相關層次結構圖(相關資源來自網絡):
Map接口中最常用到的實現類有HashMap(無序,快速訪問元素)、LinkedHashMap(按照添加順序排序,快速訪問)、TreeMap(按照鍵的比較升序排列)
接口Map<K,V>
public interface Map<K,V>
Map<K,V>接口是Map層次的根接口,與Collection<T>接口不同的是,該接口是真正的根接口,並沒有拓展自其他的接口。
Map提供將鍵映射到值的對象,一個映射不能包括重復的鍵;每個鍵最多只能映射到一個值(但是值的類型可以為單值類型比如String,也可以為多值類型比如List)。Map接口提供三種collection視圖,允許以鍵集,值集,或鍵值對映射關系集的形式對某個映射進行查看。映射順序定義為迭代器在映射的collection視圖上返回其元素的順序。某些映射實現可明確保證其順序,如 TreeMap、LinkedHashMap 類;另一些映射實現則不保證順序,如 HashMap 類。
某些映射實現對可能包含的鍵和值有所限制。例如,某些實現禁止 null 鍵和值,另一些則對其鍵的類型有限制。
抽象類AbstractMap<K,V>
public abstract class AbstractMap<K,V> implements Map<K,V>
此類提供了Map接口的骨干實現,其功能類似於Collection接口中的AbstractCollection,都是以最大限度減少實現相應接口所需的工作。此類沒有實現的方法為entrySet(),同時限制了put(K key,V value)方法。
要實現不可修改的映射,只需要擴展AbstracMap類,並提供entrySet方法的實現,該實現返回鍵-值的映射關系set視圖。通常返回的set將依次在AbstractSet(Set接口的骨干實現)上實現。此set不支持add或者remove方法,其迭代器也不支持remove方法。(啥意思???)
要實現可修改的映射,除了實現entrySet方法外,還需要實現AbstractMap類的put方法,此類對該方法進行了限制,如果沒有重寫調用此類或拋出UnsupportedOperationException,此外entrySet().iterator()返回的迭代器也必須另外實現其remove()方法。
類HashMap
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
HashMap是基於哈希表的Map接口的實現。該類是常用的映射。此實現提供了Map接口定義的所有可選的映射操作,允許使用null鍵和null值。(除了非同步和允許使用null值外,HashMap類與HashTable<已過期>大致相同)。此類不保證映射的順序,特別是它不保證該順序永久不變。
迭代 collection 視圖所需的時間與 HashMap 實例的“容量”(桶的數量)及其大小(鍵-值映射關系數)成比例。所以,如果迭代性能很重要,則不要將初始容量設置得太高(或將加載因子設置得太低)。
HashMap 的實例有兩個參數影響其性能:初始容量(默認16)和加載因子(默認0.75)。
注意,此實現不是同步的。
同List相同所有此類的“collection 視圖方法”所返回的迭代器都是快速失敗 的:在迭代器創建之後,如果從結構上對映射進行修改,除非通過迭代器本身的 remove 方法,其他任何時間任何方式的修改,迭代器都將拋出 ConcurrentModificationException
。
類LinkedHashMap<K,V>
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
Map 接口的哈希表和鏈接列表實現,具有可預知的迭代順序。此類提供所有可選的 Map 操作,並且允許 null 元素。由於增加了維護鏈接列表的開支,其性能很可能比 HashMap 稍遜一籌,不過這一點例外:LinkedHashMap 的 collection 視圖迭代所需時間只與映射的大小成比例。HashMap 迭代時間很可能開支較大,因為它所需要的時間與其容量 成比例。
此鏈接列表定義了迭代順序,該迭代順序通常就是將鍵插入到映射中的順序(插入順序)。注意,如果在映射中重新插入鍵,則插入順序不受影響。
注意,此實現不是同步的。
結構修改是指添加或刪除一個或多個映射關系,或者在按訪問順序鏈接的哈希映射中影響迭代順序的任何操作。在按插入順序鏈接的哈希映射中,僅更改與映射中已包含鍵關聯的值不是結構修改。在按訪問順序鏈接的哈希映射中,僅利用 get 查詢映射不是結構修改。
同HashMap一樣,Collection(由此類的所有 collection 視圖方法所返回)的 iterator 方法返回的迭代器都是快速失敗的。
LinkedHashMap由於是繼承了HashMap,所以其實現是在HashMap的基礎上,通過維護連接列表使其具有了可預知的迭代順序的特性。此類覆蓋了HashMap類中的get()、clear()、 containsValue()方法。
注意:通過調用get()返回 null
值並不一定表明此映射不包含該鍵的映射關系;也可能此映射將該鍵顯式地映射為 null
。可使用 containsKey()
操作來區分這兩種情況。