聲明:原創(chuàng)文章,轉(zhuǎn)載請注明出處。http://m.itdecent.cn/u/e02df63eaa87
1、Map
Map主要用于存儲健值對,根據(jù)鍵得到值,因此不允許鍵重復(fù),但允許值重復(fù)。
2、HashMap
Hashmap 是一個(gè)最常用的Map,它根據(jù)鍵的HashCode值存儲數(shù)據(jù),根據(jù)鍵可以直接獲取它的值,具有很快的訪問速度,遍歷時(shí),取得數(shù)據(jù)的順序是完全隨機(jī)的。
- HashMap最多只允許一條記錄的鍵為Null;允許多條記錄的值為 Null;
- HashMap不支持線程的同步,即任一時(shí)刻可以有多個(gè)線程同時(shí)寫HashMap;可能會導(dǎo)致數(shù)據(jù)的不一致。
- HashMap在多線程情況下,rehash過程中有可能導(dǎo)致Entry產(chǎn)生環(huán)形鏈,導(dǎo)致程序出現(xiàn)死循環(huán)。
如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
3、HashTable
Hashtable與 HashMap類似,它繼承自Dictionary類,不同的是:它不允許記錄的鍵或者值為空(空指針異常);它支持線程的同步,即任一時(shí)刻只有一個(gè)線程能寫Hashtable,因此也導(dǎo)致了 Hashtable在寫入時(shí)會比較慢。
HashTable容器使用synchronized來保證讀寫的線程安全,在競爭激烈的情況下效率非常低下。因?yàn)楫?dāng)一個(gè)線程訪問HashTable的同步方法時(shí),訪問其他同步方法的線程可能會進(jìn)入阻塞或者輪詢狀態(tài)。如線程1使用put添加元素,線程2不但不能使用put添加元素,也不能使用get獲取元素,因此競爭越激烈效率越低。
4、LinkedHashMap
LinkedHashMap 是HashMap的一個(gè)子類,保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時(shí),先得到的記錄肯定是先插入的。也可以在構(gòu)造時(shí)用帶參數(shù),按照訪問順序排序。
在遍歷的時(shí)候會比HashMap慢,不過有種情況例外,當(dāng)HashMap容量很大,實(shí)際數(shù)據(jù)較少時(shí),遍歷起來可能會比 LinkedHashMap慢,因?yàn)長inkedHashMap的遍歷速度只和實(shí)際數(shù)據(jù)有關(guān),和容量無關(guān),而HashMap的遍歷速度和他的容量有關(guān)。
根據(jù)鏈表中元素的順序可以分為:按插入順序的鏈表(默認(rèn),false),和按訪問順序的鏈表(調(diào)用get方法)。默認(rèn)是按插入順序排序,如果指定按訪問順序排序,那么調(diào)用get方法后,會將這次訪問的元素移至鏈表尾部,不斷訪問可以形成按訪問順序排序的鏈表。 可以重寫removeEldestEntry方法返回true值指定插入元素時(shí)移除最老的元素。
5、TreeMap
TreeMap實(shí)現(xiàn)SortMap接口,能夠把它保存的記錄根據(jù)鍵排序,默認(rèn)是按鍵值的升序排序,也可以指定排序的比較器,當(dāng)用Iterator 遍歷TreeMap時(shí),得到的記錄是排過序的。
6、ConcurrentHashMap
使用背景:
- HashMap線程不安全。多線程進(jìn)行put()操作可能會引起死循環(huán)。這是因?yàn)?,多線程會導(dǎo)致HashMap的Entry鏈表形成環(huán)形結(jié)構(gòu),一旦形成環(huán)形結(jié)構(gòu),Entry的next節(jié)點(diǎn)永遠(yuǎn)不為空,就會產(chǎn)生死循環(huán)。
- HashTable效率低下。HashTable使用Synchronized來保證線程安全,在線程競爭激烈的情況下,效率低下。因?yàn)楫?dāng)一個(gè)線程訪問HashTable的同步方法(put),其他線程也訪問HashTable的同步方法(put/get)時(shí),會進(jìn)入阻塞或輪詢狀態(tài)。
ConcurrentHashMap在JDK1.7版本使用分段鎖技術(shù),將數(shù)據(jù)分成一段一段的存儲,然后給每一段數(shù)據(jù)配一把鎖,當(dāng)一個(gè)線程占用鎖訪問一個(gè)段數(shù)據(jù)時(shí),其他段的數(shù)據(jù)也能被其他線程訪問,能實(shí)現(xiàn)并發(fā)訪問。而在JDK1.8版本上,則采用CAS+Synchronized的方式實(shí)現(xiàn)并發(fā)訪問。
7、總結(jié)
一般情況下,我們用的最多的是HashMap,在Map 中插入、刪除和定位元素,HashMap 是最好的選擇。
但如果您要按自然順序或自定義順序遍歷鍵,那么TreeMap會更好。
如果需要輸出的順序和輸入的相同,那么用LinkedHashMap 可以實(shí)現(xiàn),它還可以按讀取順序來排列。
HashMap是一個(gè)最常用的Map,它根據(jù)鍵的hashCode值存儲數(shù)據(jù),根據(jù)鍵可以直接獲取它的值,具有很快的訪問速度。HashMap最多只允許一條記錄的鍵為NULL,允許多條記錄的值為NULL。
HashMap不支持線程同步,即任一時(shí)刻可以有多個(gè)線程同時(shí)寫HashMap,可能會導(dǎo)致數(shù)據(jù)的不一致性。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。
Hashtable與HashMap類似,不同的是:它不允許記錄的鍵或者值為空;它支持線程的同步,即任一時(shí)刻只有一個(gè)線程能寫Hashtable,因此也導(dǎo)致了Hashtable在寫入時(shí)會比較慢。
LinkedHashMap保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時(shí),先得到的記錄肯定是先插入的。
在遍歷的時(shí)候會比HashMap慢TreeMap能夠把它保存的記錄根據(jù)鍵排序,默認(rèn)是按升序排序,也可以指定排序的比較器。當(dāng)用Iterator遍歷TreeMap時(shí),得到的記錄是排過序的。