-
public class LinkedHashMap<K,V>
- extends HashMap<K,V>
- implements Map<K,V>
Map 接口的哈希表和鏈接列表實(shí)現(xiàn),具有可預(yù)知的迭代順序。此實(shí)現(xiàn)與 HashMap 的不同之處在于,后者維護(hù)著一個(gè)運(yùn)行于所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序,該迭代順序通常就是將鍵插入到映射中的順序(插入順序)。注意,如果在映射中重新插入 鍵,則插入順序不受影響。(如果在調(diào)用 m.put(k, v) 前 m.containsKey(k) 返回了 true,則調(diào)用時(shí)會(huì)將鍵 k 重新插入到映射 m 中。)
此實(shí)現(xiàn)可以讓客戶(hù)避免未指定的、由 HashMap
(及 Hashtable
)所提供的通常為雜亂無(wú)章的排序工作,同時(shí)無(wú)需增加與 TreeMap
相關(guān)的成本。使用它可以生成一個(gè)與原來(lái)順序相同的映射副本,而與原映射的實(shí)現(xiàn)無(wú)關(guān):
void foo(Map m) {
Map copy = new LinkedHashMap(m);
...
}
如果模塊通過(guò)輸入得到一個(gè)映射,復(fù)制這個(gè)映射,然后返回由此副本確定其順序的結(jié)果,這種情況下這項(xiàng)技術(shù)特別有用。(客戶(hù)通常期望返回的內(nèi)容與其出現(xiàn)的順序相同。)
提供特殊的構(gòu)造方法
來(lái)創(chuàng)建鏈接哈希映射,該哈希映射的迭代順序就是最后訪(fǎng)問(wèn)其條目的順序,從近期訪(fǎng)問(wèn)最少到近期訪(fǎng)問(wèn)最多的順序(訪(fǎng)問(wèn)順序)。這種映射很適合構(gòu)建 LRU 緩存。調(diào)用 put 或 get 方法將會(huì)訪(fǎng)問(wèn)相應(yīng)的條目(假定調(diào)用完成后它還存在)。putAll 方法以指定映射的條目集合迭代器提供的鍵-值映射關(guān)系的順序,為指定映射的每個(gè)映射關(guān)系生成一個(gè)條目訪(fǎng)問(wèn)。任何其他方法均不生成條目訪(fǎng)問(wèn)。特別是,collection 視圖上的操作不 影響底層映射的迭代順序。
可以重寫(xiě) removeEldestEntry(Map.Entry)
方法來(lái)實(shí)施策略,以便在將新映射關(guān)系添加到映射時(shí)自動(dòng)移除舊的映射關(guān)系。
此類(lèi)提供所有可選的 Map 操作,并且允許 null 元素。與 HashMap 一樣,它可以為基本操作(add、contains 和 remove)提供穩(wěn)定的性能,假定哈希函數(shù)將元素正確分布到桶中。由于增加了維護(hù)鏈接列表的開(kāi)支,其性能很可能比 HashMap 稍遜一籌,不過(guò)這一點(diǎn)例外:LinkedHashMap 的 collection 視圖迭代所需時(shí)間與映射的大小 成比例。HashMap 迭代時(shí)間很可能開(kāi)支較大,因?yàn)樗枰臅r(shí)間與其容量 成比例。
鏈接的哈希映射具有兩個(gè)影響其性能的參數(shù):初始容量和加載因子。它們的定義與 HashMap 極其相似。要注意,為初始容量選擇非常高的值對(duì)此類(lèi)的影響比對(duì) HashMap 要小,因?yàn)榇祟?lèi)的迭代時(shí)間不受容量的影響。
注意,此實(shí)現(xiàn)不是同步的。如果多個(gè)線(xiàn)程同時(shí)訪(fǎng)問(wèn)鏈接的哈希映射,而其中至少一個(gè)線(xiàn)程從結(jié)構(gòu)上修改了該映射,則它必須 保持外部同步。這一般通過(guò)對(duì)自然封裝該映射的對(duì)象進(jìn)行同步操作來(lái)完成。如果不存在這樣的對(duì)象,則應(yīng)該使用 Collections.synchronizedMap 方法來(lái)“包裝”該映射。最好在創(chuàng)建時(shí)完成這一操作,以防止意外的非同步訪(fǎng)問(wèn):
Map m = Collections.synchronizedMap(new LinkedHashMap(...));
結(jié)構(gòu)修改是指添加或刪除一個(gè)或多個(gè)映射關(guān)系,或者在按訪(fǎng)問(wèn)順序鏈接的哈希映射中影響迭代順序的任何操作。在按插入順序鏈接的哈希映射中,僅更改與映射中已包含鍵關(guān)聯(lián)的值不是結(jié)構(gòu)修改。
在按訪(fǎng)問(wèn)順序鏈接的哈希映射中,僅利用 get 查詢(xún)映射不是結(jié)構(gòu)修改。)
Collection(由此類(lèi)的所有 collection 視圖方法所返回)的 iterator 方法返回的迭代器都是快速失敗 的:在迭代器創(chuàng)建之后,如果從結(jié)構(gòu)上對(duì)映射進(jìn)行修改,除非通過(guò)迭代器自身的移除方法,其他任何時(shí)間任何方式的修改,迭代器都將拋出 ConcurrentModificationException。因此,面對(duì)并發(fā)的修改,迭代器很快就會(huì)完全失敗,而不冒將來(lái)不確定的時(shí)間任意發(fā)生不確定行為的風(fēng)險(xiǎn)。
注意,迭代器的快速失敗行為無(wú)法得到保證,因?yàn)橐话銇?lái)說(shuō),不可能對(duì)是否出現(xiàn)不同步并發(fā)修改做出任何硬性保證。快速失敗迭代器會(huì)盡最大努力拋出 ConcurrentModificationException。因此,編寫(xiě)依賴(lài)于此異常的程序的方式是錯(cuò)誤的,正確做法是:迭代器的快速失敗行為應(yīng)該僅用于檢測(cè)程序錯(cuò)誤。
此類(lèi)是 Java Collections Framework 的成員。