資料容器
在程式**中,用來暫時儲存資料的「盒子」(容器),用於後續的邏輯處理。
為什麼需要map?
map是資料容器中的一種資料結構,首先它是用來儲存資料的;其次,與其它資料容器不同,它是一種可以通過業務資料來快速、精確檢索另乙個業務資料的資料結構。
map:是一種key-value的資料結構;key和value都是業務資料,value是最終的業務資料,key是專門用來快速定位value在map中的位置。
陣列和list也可以通過下標精確定位到業務資料,但必須「記住」下標與業務資料的關係才能在下次使用時精確定位,否則仍然需要遍歷所有資料。map自動維護了「下標(key)」與value的關係,且這個「下標」是乙個可以人為記憶的值,而不是像0,1,2...這樣乾巴巴不利於記憶的數字。
為什麼需要hashmap
hashmap實現了map介面,且key的定位是通過key的hashcode實現;hashcode是一種簡單快速的實現方式,因此hashmap效能很高。 當需要儲存key-value資料型別,又需要通過key高效能查詢value時,可以使用map。
hashmap的資料結構
結構:陣列 + 鍊錶(或紅黑樹-鍊錶長度大於等於8時自動轉化為紅黑樹)
原理:通過 「下標=key.hashcode%容量 」(這裡為了簡化原理,實際上是通過位運算實現,效果類似)計算出陣列下標。
a:hashmap主儲存結構是乙個容量預設為16的陣列;(初始建立的hashmap陣列長度為0,第一次儲存資料時擴容為16;長度為2n次方-後面會說明原因)
b:hashmap最終儲存的資料結構是一批實現了map.entry的node物件
c:node的資料結構為:
key:業務資料,為node資料指定其在陣列中的下標位置,並用於後續精確檢索當前node,這也是hashmap高效能的原因。
value:業務資料,真正用於業務計算的資料,最終的目標資料。它的儲存與檢索都通過key來實現(當然自己即可做為key也可做為value);
hash:key對應的hash值;hash值與map中陣列容量計算出的下標越雜湊,資料的在陣列中的分布越均勻,也越不容易衝突。
next:由於陣列長度有限,通過不同key的hashcode計算的陣列下標很可能衝突(兩個不同key計算的下標為同乙個陣列位置),此時通過陣列下的鍊錶來實現。next指向下乙個node.
jdk8增加了:鍊錶長度大於或等於8時,鍊錶自動轉化為紅黑樹。紅黑樹多次刪除結節後,長度小於等於6時再次轉化為鍊錶。
原因:鍊錶轉化為紅黑樹的目的是防止鍊錶過長,增大因遍而導致的效能下降。
擴充套件知識:紅黑樹-簡化理解為:乙個平衡二叉樹(所謂平衡即多次操作後,樹不會變成乙個鍊錶)
特點
a:key和value都可以為null
b:執行緒不安全
c:元素是無序的
d:與hashtable相比:除了 key/value可以為空、執行緒不安全,基本是一樣。
擴容
a:新建立的hashmap(預設構造器)時,陣列為空
b:第一次put資料或非預設構造器建立時,陣列進行第一次擴容(初始化):建立乙個預設容量(1<< 4= 16) 的陣列
c:當多次put後,陣列元素個數 > 陣列容量 * 載入因子 時,再次進行擴容:建立乙個新的陣列( old容量 << 1 即擴容1倍),把源資料複製到新陣列中
d:最大容量為integer最大值
f:預設擴容因子:default_load_factor =0.75 :結合時間和空間效率考慮得到的
容量
為什麼容量是2的冪數?
hashmap是通過「位與」運算,而不是通過取模來計算下標(為了效率考慮)。如果是2 的冪數,那麼容量的人進製則全為:1。key的hashcode與容量進行「與」時,計算的結果只與key的hashcode後幾位有關。(且記:此處僅僅為演示,實際並不是直接使用key的源hashcode,而是通過hashcode高低位異或取得,具體檢視原始碼)
如下:(length-1) & key.hashcode
發現:如果length不為2的冪,進行位執行計算下標時,碰撞的機率非常大,鍊錶真的可能性變高。而2的冪,下標只與hashcode後幾位相關,因此只要保證hashcode均勻即可。
操作過程
a:put操作:
b:get操作
原理同put,先獲取下標,定位到鍊錶在陣列中的位置,再迴圈鍊錶或紅黑樹查詢,通過equals()方法定位具體物件(key和value同時equals())。
存在問題
執行緒不安全
java基礎之容器
專門用來存放其它類的物件,這個類就叫做容器,或者就叫做集合,集合就是將若干性質相同或相近的類物件組合在一起而形成的乙個整體 陣列也可以用於儲存多個物件,那麼為什麼要引入容器呢?引入容器的原因 1 陣列的長度難以擴充 2 陣列中資料的型別必須相同 容器與陣列的區別與聯絡 1 容器不是陣列,不能通過下標...
iOS基礎之容器
cocoa touch基礎框架提供比較常用的容器類物件 nsarray nsdicitonary nsset nsindex 1.nsarray和它的子類nsmutablearray 它們相當於陣列,可以持有不同型別的objective c物件,其他型別。比如說c型別的整型 浮點型 列舉型和結構體指...
java容器之Map介面
hashmap類 在介紹hashmap之前,有必要介紹下關於雜湊表的知識。太久沒用到雜湊表,沒想到一時竟然忘記了它的存在的意義了,看來不多做筆記真不行 雜湊表 支援以常數時間對任何命名項的檢索或刪除。為什麼能夠這麼會有這種效果呢?原理是 定義乙個空的tablesize大小陣列,每個要插入元素根據雜湊...