一文帶你弄清Map集合及其實(shí)現(xiàn)類(lèi)
Map接口的一些重要方法:
V get(Object key):返回與指定鍵相關(guān)聯(lián)的值,如果不存在則返回null。 V put(K key, V value):將指定的鍵值對(duì)存儲(chǔ)到Map中,如果鍵已經(jīng)存在,則替換對(duì)應(yīng)的值,并返回之前與該鍵相關(guān)聯(lián)的值;如果鍵不存在,則直接添加鍵值對(duì),并返回null。 V remove(Object key):從Map中刪除指定鍵的映射關(guān)系,并返回與該鍵相關(guān)聯(lián)的值,如果鍵不存在,則返回null。 boolean containsKey(Object key):檢查Map是否包含指定的鍵,如果存在則返回true,否則返回false。 boolean containsValue(Object value):檢查Map是否包含指定的值,如果存在則返回true,否則返回false。 int size():返回Map中鍵值對(duì)的數(shù)量。 boolean isEmpty():檢查Map是否為空,如果為空則返回true,否則返回false。 void clear():清空Map中的所有鍵值對(duì)。 Set keySet():返回Map中所有鍵的集合。 Collection values():返回Map中所有值的集合。 Set<Map.Entry<K, V>> entrySet():返回Map中所有鍵值對(duì)的集合。
常見(jiàn)的實(shí)現(xiàn)Map接口的類(lèi)有:
- HashMap:基于哈希表實(shí)現(xiàn),提供快速的鍵值查找和插入操作。不保證鍵值對(duì)的順序。
- LinkedHashMap:基于哈希表和雙向鏈表實(shí)現(xiàn),保留插入順序或訪問(wèn)順序(可以通過(guò)構(gòu)造函數(shù)參數(shù)指定)。
- TreeMap:基于紅黑樹(shù)實(shí)現(xiàn),按照鍵的自然順序或者指定的比較器進(jìn)行排序。
- Hashtable:早期的實(shí)現(xiàn)類(lèi),線程安全但效率較低。已經(jīng)被HashMap取代。
HashMap詳細(xì)介紹
HashMap是Java中的一種數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ)鍵值對(duì)。它實(shí)現(xiàn)了Map接口,允許我們使用一個(gè)特定的鍵來(lái)訪問(wèn)與之關(guān)聯(lián)的值。

HashMap的實(shí)現(xiàn)基于哈希表。在哈希表中,每個(gè)元素都有一個(gè)唯一的索引(哈希碼),這個(gè)索引可以用來(lái)查找對(duì)應(yīng)的值。當(dāng)我們向HashMap中添加一個(gè)新元素時(shí),它會(huì)先計(jì)算該元素的哈希碼,并將其插入到對(duì)應(yīng)位置上。
以下是HashMap類(lèi)的主要方法:
put(key, value):將指定的鍵和值添加到Map中。 get(key):返回指定鍵所映射的值。 remove(key):從Map中刪除指定鍵及其關(guān)聯(lián)的值。 containsKey(key):判斷Map是否包含指定鍵。 keySet():返回Map中所有鍵組成的Set集合。
需要注意的幾點(diǎn)是:
- HashMap允許使用null作為key和value。
- 如果多個(gè)元素映射到同一個(gè)索引位置上,則會(huì)產(chǎn)生沖突。HashMap采用鏈?zhǔn)酱鎯?chǔ)解決沖突問(wèn)題,即在相應(yīng)位置上維護(hù)一個(gè)鏈表,將具有相同索引位置的元素串起來(lái)。這樣,在查找時(shí)只需遍歷相應(yīng)鏈表即可。 在處理大量數(shù)據(jù)時(shí),由于哈希碰撞可能會(huì)影響性能,因此我們需要選擇一個(gè)合適的哈希函數(shù)來(lái)減少碰撞的可能性。
- HashMap不是線程安全的,如果在多線程環(huán)境下使用HashMap,需要進(jìn)行額外的同步操作。同時(shí)Java也提供了線程安全的ConcurrentHashMap類(lèi)。
JDK.17和JDK1.8的HashMap有什么區(qū)別
JDK 1.7和JDK 1.8都提供了HashMap類(lèi),但是它們的實(shí)現(xiàn)方式有所不同。下面對(duì)這兩個(gè)版本的HashMap做一個(gè)詳細(xì)的介紹:
JDK 1.7的HashMap
JDK 1.7的HashMap是基于數(shù)組和鏈表組合實(shí)現(xiàn)的。HashMap中的每個(gè)元素都是一個(gè)Entry對(duì)象,其中包含了一個(gè)key-value對(duì)和next指針。當(dāng)我們往HashMap中添加元素時(shí),程序會(huì)根據(jù)key的hashCode值計(jì)算出元素在數(shù)組中的位置,如果該位置還沒(méi)有存放任何元素,那么直接將新元素放入該位置即可。如果該位置已經(jīng)存在其他元素,那么它們會(huì)被當(dāng)作一個(gè)鏈表存放在該位置上,新元素會(huì)被插入到鏈表的尾部。當(dāng)遍歷HashMap時(shí),程序會(huì)首先根據(jù)key的hashCode值確定該元素在數(shù)組中的位置,然后遍歷該位置上的鏈表,找到對(duì)應(yīng)的Entry對(duì)象。
但是,JDK 1.7的HashMap存在一個(gè)很?chē)?yán)重的問(wèn)題,就是在多線程環(huán)境下,如果多個(gè)線程對(duì)HashMap進(jìn)行并發(fā)修改,可能會(huì)導(dǎo)致鏈表成環(huán)形而死循環(huán),從而引發(fā)程序崩潰。因此,在JDK 1.7中,如果需要在多線程下使用HashMap,我們必須手動(dòng)實(shí)現(xiàn)同步機(jī)制。
JDK 1.8的HashMap
JDK 1.8的HashMap也是基于數(shù)組和鏈表組合實(shí)現(xiàn)的,但是在實(shí)現(xiàn)方式上有了較大的改進(jìn)。JDK 1.8的HashMap采用了紅黑樹(shù)的數(shù)據(jù)結(jié)構(gòu)來(lái)代替鏈表,這樣可以保證在大量元素存儲(chǔ)時(shí),當(dāng)鏈表長(zhǎng)度超過(guò)一定閾值時(shí),將鏈表轉(zhuǎn)換成紅黑樹(shù),從而提高查找、添加和刪除操作的效率。
同時(shí),JDK 1.8的HashMap還針對(duì)并發(fā)修改問(wèn)題進(jìn)行了優(yōu)化。它使用了一種叫做**“分段鎖”**的機(jī)制來(lái)代替?zhèn)鹘y(tǒng)的同步鎖,將一個(gè)大的HashMap切分成多個(gè)小的HashMap,每個(gè)小的HashMap都由一個(gè)獨(dú)立的鎖進(jìn)行控制,這樣多個(gè)線程對(duì)不同的小HashMap進(jìn)行修改時(shí),就不會(huì)發(fā)生死循環(huán)的情況了。
除此之外,JDK 1.8的HashMap還引入了一些新的方法,例如forEach()、replaceAll()等,以便我們更加方便地操作HashMap中的元素。此外,JDK 1.8的HashMap對(duì)JDK 1.7的問(wèn)題進(jìn)行了修復(fù)和優(yōu)化,因此在實(shí)際使用中,推薦盡量使用JDK 1.8的HashMap。
TreeMap詳細(xì)介紹
TreeMap是Java中的一種數(shù)據(jù)結(jié)構(gòu),它實(shí)現(xiàn)了NavigableMap接口,而NavigableMap接口又繼承了SortedMap接口,它能夠根據(jù)鍵值進(jìn)行排序,并且基于紅黑樹(shù)實(shí)現(xiàn)。因此,它保證了插入、刪除和查找操作的時(shí)間復(fù)雜度均為O(logN)。

以下是TreeMap的幾個(gè)特性:
有序性:TreeMap會(huì)根據(jù)鍵的自然順序或者指定的比較器對(duì)鍵進(jìn)行排序,并保持有序狀態(tài)。在插入、刪除和查詢(xún)操作時(shí),TreeMap會(huì)保持鍵的有序性。
唯一鍵:TreeMap的鍵是唯一的,不允許重復(fù)的鍵。如果添加的鍵已經(jīng)存在,則新值將替代舊值。
快速插入、刪除和查詢(xún):TreeMap基于紅黑樹(shù)實(shí)現(xiàn),具有快速的插入、刪除和查詢(xún)操作。平均情況下,這些操作的時(shí)間復(fù)雜度是O(logN),其中N表示鍵值對(duì)的數(shù)量。
線程不安全:TreeMap不是線程安全的,如果多個(gè)線程同時(shí)訪問(wèn)一個(gè)TreeMap對(duì)象并進(jìn)行修改操作,可能會(huì)導(dǎo)致不確定的結(jié)果。如果需要在多線程環(huán)境下使用Map,可以考慮使用ConcurrentSkipListMap或通過(guò)synchronized關(guān)鍵字保證線程安全。
允許null鍵(僅限于沒(méi)有指定比較器時(shí)):TreeMap允許存儲(chǔ)null鍵。但是需要注意的是,如果在創(chuàng)建TreeMap時(shí)指定了比較器,則不允許null鍵。
我們?cè)谑褂脮r(shí)需要注意以下幾點(diǎn):
- TreeMap允許使用null作為value,但不允許使用null作為key。如果嘗試存儲(chǔ)null作為key,則會(huì)拋出NullPointerException異常。
- TreeMap默認(rèn)情況下按照升序排列元素。如果需要改變排序方式,則可以通過(guò)提供自定義比較器來(lái)實(shí)現(xiàn)。例如,我們可以創(chuàng)建一個(gè)按照字符串長(zhǎng)度降序排列元素的TreeMap:
Map<String, Integer> map = new TreeMap<>((o1, o2) -> o2.length() - o1.length());
- 和HashMap一樣,TreeMap也不是線程安全的。如果在多線程環(huán)境下使用TreeMap,需要進(jìn)行額外的同步操作。同時(shí)Java也提供了線程安全的ConcurrentSkipListMap類(lèi)。
到此這篇關(guān)于一文帶你弄清Map集合及其實(shí)現(xiàn)類(lèi)的文章就介紹到這了,更多相關(guān)Map集合及實(shí)現(xiàn)類(lèi)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JUC循環(huán)屏障CyclicBarrier與CountDownLatch區(qū)別詳解
這篇文章主要為大家介紹了JUC循環(huán)屏障CyclicBarrier與CountDownLatch區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Spring Data JPA 設(shè)置字段默認(rèn)值方式
這篇文章主要介紹了Spring Data JPA設(shè)置字段默認(rèn)值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
java判斷一個(gè)文件是否為二進(jìn)制文件的方法
這篇文章主要介紹了java判斷一個(gè)文件是否為二進(jìn)制文件的方法,涉及java針對(duì)文件的讀取及編碼判斷技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07
詳解java設(shè)計(jì)模式中的門(mén)面模式
門(mén)面模式又叫外觀模式(Facade?Pattern),主要用于隱藏系統(tǒng)的復(fù)雜性,并向客戶(hù)端提供了一個(gè)客戶(hù)端可以訪問(wèn)系統(tǒng)的接口,本文通過(guò)實(shí)例代碼給大家介紹下java門(mén)面模式的相關(guān)知識(shí),感興趣的朋友一起看看吧2022-02-02
Java 異步回調(diào)機(jī)制實(shí)例分析
這篇文章主要介紹了Java 異步回調(diào)機(jī)制實(shí)例解析的相關(guān)資料,需要的朋友可以參考下2017-02-02
Java快速排序的實(shí)現(xiàn)詳細(xì)代碼及通俗解釋
這篇文章主要介紹了Java快速排序?qū)崿F(xiàn)的相關(guān)資料,快速排序是一種高效的排序算法,通過(guò)選擇一個(gè)基準(zhǔn)值將數(shù)組分成兩部分,左邊的元素比基準(zhǔn)值小,右邊的元素比基準(zhǔn)值大,然后遞歸地對(duì)這兩部分進(jìn)行排序,需要的朋友可以參考下2025-02-02
JAVA反射機(jī)制中g(shù)etClass和class對(duì)比分析
這篇文章主要介紹了JAVA反射機(jī)制中g(shù)etClass和class對(duì)比分析,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11

