Java集合歸納-Map

Map概要

上一篇總結了Set集合的一些常用知識點,爲何緊接着總結Map呢?

因爲Map和Set在底層實現上可以說是一種包裝的關係,先看看Map的結構示意圖。

這裏寫圖片描述

上圖中的兩個桶分別代表Map集合裏保存的兩組值,分別是Key值和Value值,Key和Value都可以是任何引用類型且他們之間保持着一一對應的關係,這一點是Map最基本的。Key值不允許重複,且無需,是不是和Set很像呢,其實把Map裏的所有Key值拉出來單獨看,就是一個Set集合,沒有順序,不可重複。

而如果我們把Map中所有的Value放在一起,他們就又很類似一個List結構,即元素之間可以重複,每個元素都通過“索引”查找,只不過Map的索引不是整型而是Key值而已。

就像在第一章節Java集合歸納-<一>集合概述中說的那樣,Set的實現可以說就是一個所有value值爲null的Map結構,Java先實現了Map,再包裝一個所有value值爲null的Map來實現Set。基於這一點,可以在熟悉Set之後更加方便的牢記Map的特性,反之亦可。就連他們倆之間的子類實現都是同出一轍,HashMap、LinkedHashMap、SortedMap(Interface)、TreeMap。

entrySet和keySet

Map接口中定義的方法都是針對Map中存儲對象引用的查詢和操作,實際使用過程中根據方法名都能大概推測其功能,這裏就不過多贅述,只挑幾個比較值得一說的功能來看。

  • Set entrySet():返回Map中存儲的Key-Value對所組成的Set集合,每個元素都是Map.Entry,Entry是Map的內部類,可以理解爲一個桶(bucket)的入口。
  • Set keySet():返回該Map中存儲的所有Key值所組成的集合

有Key的Set,有Key-Value的Set,爲什麼沒有Value的Set,因爲Value可重複,從這個設定又可以反應Value存儲的特性,加深我們對Map集合特性的記憶。

上面兩個方法,經常可以用來對Map集合存儲的元素進行迭代遍歷,對Map中的對象有一個宏觀的把控。

HashMap和Hashtable

區別

  • Hashtable(注意寫法)是一個線程安全的Map子類實現,而HashMap不是線程安全的Map子類實現。相對的,HashMap的性能會更好,大部分情況下,不考慮多線程環境下的運行時,我們都應該選擇使用HashMap
  • Hashtable不允許使用null作爲Key或者Value值,HashMap可以,但要注意的是HashMap的Key值也只允許存在一個爲null的對象,畢竟Key值還是要遵循Map的不可重複性。

Hashtable與Vector

爲什麼把這兩個集合放在一起講,是因爲他們的“命運”是相似的,都是古老的Java類,甚至Hashtable的命名規則都沒有遵循Java的命名規範,他們都有一些古老版本下的操作方法,有些方法名長而複雜,現在都已經逐漸被Collections工具類的Synchronize修飾符所取代,比如synchronizeMap()等等。

hashCode()和equals()

與Set類似,HashMap和Hashtable也不能保證集合中元素的順序,因此就需要保證Key值得唯一性。爲了Key值得唯一性,就需要一個判斷Key值是否相等的標準,這個標準就是:兩個Key值通過equals()方法比較返回true,那麼兩個Key的hashCode()返回的值也應該相等

插入元素判定流程圖

這裏寫圖片描述

簡單的畫了一個插入元素時,HashMap和Hashtable的判定流程圖,說一下圖中紅字條件爲NO的兩條判定線,這兩種插入情況有點區別。

  • Type1:hashCode()返回值不一樣,說明兩個Key值在hash表中的存儲地址不一樣,新插入的元素和其他元素一樣,散列在hash表的各個bucket(桶)下,此時的存儲性能是最優的。
  • Type2:hashCode()返回值一樣,Key的值equals()返回false,說明此時新插入的元素和集合中某一元素存儲地址相等,他們將會放在同一個bucket(桶)下,以鏈表維護,如下圖所示。

這裏寫圖片描述

所以這也是爲什麼我們常說,HashMap和Hashtable其實就是一個以數組爲主體,鏈表解決“哈希衝突”的集合

SortedMap接口和TreeMap

和Set的派生設置一樣,Map也有一個SortedMap接口和一個它的實現類TreeMap。TreeMap的底層就是由一個紅黑樹數據結構實現的,每一個鍵值對都是紅黑樹的一個節點,所以瞭解紅黑樹結構對於理解TreeMap有很重要的意義。關於紅黑樹的介紹,我推薦大家看看這篇文章紅黑樹(一)之 原理和算法詳細介紹,作者講得很細緻生動,看一遍就能有一個大致的體會。

Comparable接口和compareTo()方法

和HashMap、Hashtable類似,他們判斷元素相等的標準有equals()和hashCode(),TreeMap自己的判斷標準則是Comparable接口下的compareTo()方法,當兩個元素的Key值通過compareTo()畢竟返回0時,說明兩個元素的Key值是相等的。因此,TreeMap中存放的元素都要求實現Comparable接口,這點和之前講過的TreeSet一致。

總結

Map的常用實現類HashMap、Hashtable、TreeMap。

  • HashMap和Hashtable的實現機制幾乎一樣,區別在於,Hashtable是古老的線程安全集合,性能較HashMap來說更差一些。
  • TreeMap通常比HashMap和Hashtable都要慢,因爲它的底層需要樹結構去維護元素之間的次序,所以TreeMap中的鍵值對總是處於排序狀態,無須對其內部元素進行排序操作。在實際應用中,我們可以調用TreeMap的keySet()方法獲取TreeMap中所有Key排好序的Set集合,通過toArray()方法生成Key數組,並使用Arrays的binarySearch()方法對於已排好序的數組做二分查找,效率很高。
  • 除非我們需要Map中的元素維持有序狀態,否則我們都應當優先考慮使用HashMap
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章