源碼:HashMap,Mybatis,Spring 建議看
HashMap: 數組+鏈表+(1.8之後紅黑樹)
Object類的hashCode:返回對象的內存地址經過處理後的結構,由於每個對象的內存地址都不一樣,所以哈希碼也不一樣
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
初始容量:1<<4 即 16.
問 爲什麼初始容量 是16?
答:java的底層是c語言,C語言底層是彙編語言,彙編再往上就是機器語言,彙編編程使用的就是16進制,因此效率越高。
內部結構
有一個Node類
Node Implement Map.entry{
hash
key
value
next
}
Map.entry
interface Entry<K,V> {
getKey()
setKey()
getValue()
setValue()
比較器,hash等抽象或具體實現的方法
}
當數據傳進來時,首先會封裝成Node,根據key取hash值,然後 hash(key) &(length()-1) ,存入數據
哈希衝突/碰撞:
1 單向鏈表:
1.8之前 可以無限掛,1.8之後只能掛7個,第8個的時候轉變爲紅黑樹。最大容量爲64,達到64再拆分。大於64會擴容。
下掛節點<=6個,會將紅黑樹再轉變爲鏈表
問:爲什麼是6個時候轉變?不是7個呢?
答:7個做準備,多一個是紅黑樹,少一個鏈表
/**
* The bin count threshold for untreeifying a (split) bin during a
* resize operation. Should be less than TREEIFY_THRESHOLD, and at
* most 6 to mesh with shrinkage detection under removal.
*/
static final int UNTREEIFY_THRESHOLD = 6;
/**
* The smallest table capacity for which bins may be treeified.
* (Otherwise the table is resized if too many nodes in a bin.)
* Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
* between resizing and treeification thresholds.
*/
static final int MIN_TREEIFY_CAPACITY = 64;
2
擴容因子0.75
初始容量16,當存到12時,會擴容成32容量
問:hashMap的擴容怎麼操作的?擴容後的元素如何均分的?
答:非常巧妙的處理:
0101 0101 0101 0101 0101 0101 0101 0101 = 每個Node的hash(key)值
0000 0000 0000 0000 0000 0000 0001 0000 = 32 容量
第五位若是0,則不變,若是1,則 當前位置 = 當前位置 +上一個容量
/**
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;