一文帶你弄清Map集合及其實現(xiàn)類
Map接口的一些重要方法:
V get(Object key):返回與指定鍵相關(guān)聯(lián)的值,如果不存在則返回null。 V put(K key, V value):將指定的鍵值對存儲到Map中,如果鍵已經(jīng)存在,則替換對應(yīng)的值,并返回之前與該鍵相關(guān)聯(lián)的值;如果鍵不存在,則直接添加鍵值對,并返回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中鍵值對的數(shù)量。 boolean isEmpty():檢查Map是否為空,如果為空則返回true,否則返回false。 void clear():清空Map中的所有鍵值對。 Set keySet():返回Map中所有鍵的集合。 Collection values():返回Map中所有值的集合。 Set<Map.Entry<K, V>> entrySet():返回Map中所有鍵值對的集合。
常見的實現(xiàn)Map接口的類有:
- HashMap:基于哈希表實現(xiàn),提供快速的鍵值查找和插入操作。不保證鍵值對的順序。
- LinkedHashMap:基于哈希表和雙向鏈表實現(xiàn),保留插入順序或訪問順序(可以通過構(gòu)造函數(shù)參數(shù)指定)。
- TreeMap:基于紅黑樹實現(xiàn),按照鍵的自然順序或者指定的比較器進行排序。
- Hashtable:早期的實現(xiàn)類,線程安全但效率較低。已經(jīng)被HashMap取代。
HashMap詳細介紹
HashMap是Java中的一種數(shù)據(jù)結(jié)構(gòu),用于存儲鍵值對。它實現(xiàn)了Map接口,允許我們使用一個特定的鍵來訪問與之關(guān)聯(lián)的值。
HashMap的實現(xiàn)基于哈希表。在哈希表中,每個元素都有一個唯一的索引(哈希碼),這個索引可以用來查找對應(yīng)的值。當(dāng)我們向HashMap中添加一個新元素時,它會先計算該元素的哈希碼,并將其插入到對應(yīng)位置上。
以下是HashMap類的主要方法:
put(key, value):將指定的鍵和值添加到Map中。 get(key):返回指定鍵所映射的值。 remove(key):從Map中刪除指定鍵及其關(guān)聯(lián)的值。 containsKey(key):判斷Map是否包含指定鍵。 keySet():返回Map中所有鍵組成的Set集合。
需要注意的幾點是:
- HashMap允許使用null作為key和value。
- 如果多個元素映射到同一個索引位置上,則會產(chǎn)生沖突。HashMap采用鏈?zhǔn)酱鎯?/strong>解決沖突問題,即在相應(yīng)位置上維護一個鏈表,將具有相同索引位置的元素串起來。這樣,在查找時只需遍歷相應(yīng)鏈表即可。 在處理大量數(shù)據(jù)時,由于哈希碰撞可能會影響性能,因此我們需要選擇一個合適的哈希函數(shù)來減少碰撞的可能性。
- HashMap不是線程安全的,如果在多線程環(huán)境下使用HashMap,需要進行額外的同步操作。同時Java也提供了線程安全的ConcurrentHashMap類。
JDK.17和JDK1.8的HashMap有什么區(qū)別
JDK 1.7和JDK 1.8都提供了HashMap類,但是它們的實現(xiàn)方式有所不同。下面對這兩個版本的HashMap做一個詳細的介紹:
JDK 1.7的HashMap
JDK 1.7的HashMap是基于數(shù)組和鏈表組合實現(xiàn)的。HashMap中的每個元素都是一個Entry對象,其中包含了一個key-value對和next指針。當(dāng)我們往HashMap中添加元素時,程序會根據(jù)key的hashCode值計算出元素在數(shù)組中的位置,如果該位置還沒有存放任何元素,那么直接將新元素放入該位置即可。如果該位置已經(jīng)存在其他元素,那么它們會被當(dāng)作一個鏈表存放在該位置上,新元素會被插入到鏈表的尾部。當(dāng)遍歷HashMap時,程序會首先根據(jù)key的hashCode值確定該元素在數(shù)組中的位置,然后遍歷該位置上的鏈表,找到對應(yīng)的Entry對象。
但是,JDK 1.7的HashMap存在一個很嚴(yán)重的問題,就是在多線程環(huán)境下,如果多個線程對HashMap進行并發(fā)修改,可能會導(dǎo)致鏈表成環(huán)形而死循環(huán),從而引發(fā)程序崩潰。因此,在JDK 1.7中,如果需要在多線程下使用HashMap,我們必須手動實現(xiàn)同步機制。
JDK 1.8的HashMap
JDK 1.8的HashMap也是基于數(shù)組和鏈表組合實現(xiàn)的,但是在實現(xiàn)方式上有了較大的改進。JDK 1.8的HashMap采用了紅黑樹的數(shù)據(jù)結(jié)構(gòu)來代替鏈表,這樣可以保證在大量元素存儲時,當(dāng)鏈表長度超過一定閾值時,將鏈表轉(zhuǎn)換成紅黑樹,從而提高查找、添加和刪除操作的效率。
同時,JDK 1.8的HashMap還針對并發(fā)修改問題進行了優(yōu)化。它使用了一種叫做**“分段鎖”**的機制來代替?zhèn)鹘y(tǒng)的同步鎖,將一個大的HashMap切分成多個小的HashMap,每個小的HashMap都由一個獨立的鎖進行控制,這樣多個線程對不同的小HashMap進行修改時,就不會發(fā)生死循環(huán)的情況了。
除此之外,JDK 1.8的HashMap還引入了一些新的方法,例如forEach()、replaceAll()等,以便我們更加方便地操作HashMap中的元素。此外,JDK 1.8的HashMap對JDK 1.7的問題進行了修復(fù)和優(yōu)化,因此在實際使用中,推薦盡量使用JDK 1.8的HashMap。
TreeMap詳細介紹
TreeMap是Java中的一種數(shù)據(jù)結(jié)構(gòu),它實現(xiàn)了NavigableMap接口,而NavigableMap接口又繼承了SortedMap接口,它能夠根據(jù)鍵值進行排序,并且基于紅黑樹實現(xiàn)。因此,它保證了插入、刪除和查找操作的時間復(fù)雜度均為O(logN)。
以下是TreeMap的幾個特性:
有序性:TreeMap會根據(jù)鍵的自然順序或者指定的比較器對鍵進行排序,并保持有序狀態(tài)。在插入、刪除和查詢操作時,TreeMap會保持鍵的有序性。
唯一鍵:TreeMap的鍵是唯一的,不允許重復(fù)的鍵。如果添加的鍵已經(jīng)存在,則新值將替代舊值。
快速插入、刪除和查詢:TreeMap基于紅黑樹實現(xiàn),具有快速的插入、刪除和查詢操作。平均情況下,這些操作的時間復(fù)雜度是O(logN),其中N表示鍵值對的數(shù)量。
線程不安全:TreeMap不是線程安全的,如果多個線程同時訪問一個TreeMap對象并進行修改操作,可能會導(dǎo)致不確定的結(jié)果。如果需要在多線程環(huán)境下使用Map,可以考慮使用ConcurrentSkipListMap或通過synchronized關(guān)鍵字保證線程安全。
允許null鍵(僅限于沒有指定比較器時):TreeMap允許存儲null鍵。但是需要注意的是,如果在創(chuàng)建TreeMap時指定了比較器,則不允許null鍵。
我們在使用時需要注意以下幾點:
- TreeMap允許使用null作為value,但不允許使用null作為key。如果嘗試存儲null作為key,則會拋出NullPointerException異常。
- TreeMap默認(rèn)情況下按照升序排列元素。如果需要改變排序方式,則可以通過提供自定義比較器來實現(xiàn)。例如,我們可以創(chuàng)建一個按照字符串長度降序排列元素的TreeMap:
Map<String, Integer> map = new TreeMap<>((o1, o2) -> o2.length() - o1.length());
- 和HashMap一樣,TreeMap也不是線程安全的。如果在多線程環(huán)境下使用TreeMap,需要進行額外的同步操作。同時Java也提供了線程安全的ConcurrentSkipListMap類。
到此這篇關(guān)于一文帶你弄清Map集合及其實現(xiàn)類的文章就介紹到這了,更多相關(guān)Map集合及實現(xiàn)類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA不可變類(immutable)機制與String的不可變性(推薦)
這篇文章主要介紹了JAVA不可變類(immutable)機制與String的不可變性(推薦)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-08-08springboot maven 項目打包jar 最后名稱自定義的教程
這篇文章主要介紹了springboot maven 項目打包jar 最后名稱自定義的教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10idea在工具欄中顯示快速創(chuàng)建包和類的圖標(biāo)的詳細步驟
點擊需要創(chuàng)建包或者類的位置,在點擊對用的圖標(biāo)就可以快速創(chuàng)建類或者包了,下面小編給大家介紹idea在工具欄中顯示快速創(chuàng)建包和類的圖標(biāo)的詳細步驟,感興趣的朋友一起看看吧2024-02-02SpringBoot配置文件bootstrap和application區(qū)別及說明
這篇文章主要介紹了SpringBoot配置文件bootstrap和application區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06如何使用攔截器獲取請求的入?yún)⒉⑵滢D(zhuǎn)化為Java對象詳解
這篇文章主要介紹了如何使用攔截器獲取請求的入?yún)⒉⑵滢D(zhuǎn)化為Java對象的相關(guān)資料,文中介紹了兩種實現(xiàn)的方法,并給出了詳細的代碼示例,需要的朋友可以參考下2025-02-02