1. 程式人生 > >HashMap的缺點/實現原理及其特點

HashMap的缺點/實現原理及其特點

1.缺陷就在於其高度依賴hash演算法,如果key是自定義類,你得自己重寫hashcode方法,寫hash演算法。

而且hashmap要求,存入時的hashcode什麼樣,之後就不能在變更,如果一個類的hashcode與其成員變數name有關,而之後name又發生了變化,那麼hashmap行為將不正常。

兩個物件如果equals相同,那hashcode的值一定相同,如果hashcode值相同,物件不一定equals相同,只能證明兩物件在雜湊儲存中處於同一位置! 在雜湊儲存中存放元素,通常先判斷hash值,確定是不是在這個位置,再判斷equals 和已存放的元素是否相等。

所以hash值又必須跟物件屬性有關係,否則無法保證equals相等 hash就等,但和屬性掛鉤,一旦屬性變化,hash就變化,處於雜湊儲存的位置就會發生變化

2.hashmap的元素儲存位置,除了元素key的hash值有關,還跟陣列本身長度有關,如果擴容陣列長度發生變化,必須把所有元素重新計算其index存放位置,所以儘可能事先確定hashmap的大小,防止擴容
--------------------- 

實現原理及其特點:

1) HashMap可以接受null鍵值和值,而HashTable則不能,HashMap是非synchronized的;儲存的是鍵值對。

2) HashMap是基於hashing原理,使用put(key,value)儲存物件到HashMap中,使用get(key)從HashMap中獲取物件,當我們給put方法傳遞鍵和值時,我們先對鍵呼叫hashCode()方法,返回的hashCode用於找到bucket位置來儲存鍵物件和值物件,作為Map.Entry.

3) 如果兩個物件hashCode相同:

儲存時:他們會找到相同的bucket位置,發生碰撞,因為HashMap使用連結串列儲存物件(每個Map.Entry都有一個next指標),這個Entry會儲存在連結串列中。

獲取時:會用hashCode找到bucket位置,然後呼叫key.equals()方法找到連結串列中正確的節點.最終找到要找的值物件.

減少碰撞:使用final修飾的物件、或不可變的物件作為鍵,使用(Integer、String)(是不可變、final的,而且已經重寫了equals和hashCode方法)這樣的wrapper類作為鍵是非常好的,(我們可以使用自定義的物件作為鍵嗎?答:當然可以,只要它遵守了equals和hashCode方法定義規則,並且當物件插入到Map中之後將不會再改變。)

4) HashMap負載因子預設是0.75,可設定,當map填滿了75%的bucket時候,將會建立原來HashMap大小兩倍的bucket陣列,來重新調整map的大小,並將原來的物件放入新的bucket陣列中,這個過程叫做rehashing,因為它呼叫hash方法找到新的bucket位置。

5) 重新調整map大小可能會發生競爭問題:如果兩個執行緒都發現HashMap需要調整大小了,它們都會嘗試進行調整,在調整中,儲存在連結串列中的元素的次序會反過來,因為移動bucket位置的時候,HashMap並不會將元素放在連結串列的尾部,而是放在頭部,這是為了避免尾部遍歷,如果條件競爭發生了,就死迴圈了。
--------------------- 
作者:byds520 
來源:CSDN 
原文:https://blog.csdn.net/lovewebeye/article/details/79573702 
版權宣告:本文為博主原創文章,轉載請附上博文連結!