package com.wkcto.hashmap;
import java.util.HashMap;
/**
* HashMap源碼分析
* @author 北京動(dòng)力節(jié)點(diǎn)
*
*/
public class Test02 {
public static void main(String[] args) {
HashMap<String, Integer> hashMap = new HashMap<>();
/*
*1) 在無參構(gòu)造方法中, 給HashMap的loadFactor字段賦值為0.75, 這是加載因子
* HashMap中定義了 Node<K,V> [] table數(shù)組, 默認(rèn)初始化 null
*/
hashMap.put("lisi", 33);
/*
* 2) 在第一次執(zhí)行put()方法添加<鍵,值>對時(shí), 給table數(shù)組初始化, 默認(rèn)初始化容量: 16
* 給threshold字段賦值 12 , 該字段的值 等于 默認(rèn)的加載因子 * 數(shù)組默認(rèn)的初始化容量
*/
/*
* 3) put()添加數(shù)據(jù)
* (1) 先根據(jù)鍵的哈希碼(hashCode()方法的返回值)計(jì)算 鍵"lisi"的hash值: 3322017
* (2) 根據(jù)hash值,計(jì)算數(shù)組的下標(biāo), i = 1
* (3) 如果table[i] == null, 根據(jù)hash,key,value值創(chuàng)建一個(gè)結(jié)點(diǎn)保存到table[i]中
* 如果table[i] !=null, 遍歷table[i]單向鏈表的每個(gè)結(jié)點(diǎn), 如果有某個(gè)結(jié)點(diǎn)的key與當(dāng)前的鍵equals()相等
* 就使用新的value值33替換原來的值; 如果所有結(jié)點(diǎn)的key都不相同,找到鏈表的尾部, 就根據(jù)當(dāng)前鍵值對生成新的結(jié)點(diǎn)插入到鏈表的尾部
* 當(dāng)單向鏈表中結(jié)點(diǎn)的數(shù)量 大于 8個(gè)時(shí), 系統(tǒng)會(huì)把單向鏈表轉(zhuǎn)換為紅黑樹,紅黑樹是由雙向鏈表實(shí)現(xiàn)的
*/
int hash = hash("lisi");
System.out.println( hash );
int n = 16; //table數(shù)組默認(rèn)的初始化容量
int i = (n - 1) & hash; //計(jì)算數(shù)組的下標(biāo)
System.out.println( i ); //1
Integer v = hashMap.get("lisi");
/*
* 4) get()返回鍵對應(yīng)的值
* (1) 根據(jù)鍵的hashCode()計(jì)算hash值
* (2) 如果table == null, 或者table.length > 0 不成立, 或者 table[i]元素為null, 直接返回null
* (3) 遍歷table[i]單向鏈表上每個(gè)結(jié)點(diǎn), 如果有某個(gè)結(jié)點(diǎn)的鍵與當(dāng)前的鍵equals()相等, 就返回該結(jié)點(diǎn)的value值, 如果沒有匹配的結(jié)點(diǎn)返回null
*/
/*
* 5) HashMap在定義時(shí), 可以指定一個(gè)初始化容量, 需要指定為2的冪次方,如果不是2的冪次方,系統(tǒng)會(huì)自動(dòng)調(diào)整為2的冪次方
* 假設(shè)初始化容量為33~63之間的數(shù),系統(tǒng)會(huì)調(diào)整為64, 為什么? 就是為了能夠快速的得出數(shù)組的下標(biāo)
* 數(shù)組的下標(biāo)計(jì)算公式: (n - 1) & hash , 把hash值與n-1進(jìn)行按位與操作
* 當(dāng)n==64時(shí), n-1的值是63,它的二進(jìn)制為 0011 1111 , 在與hash值進(jìn)行按 位與操作時(shí), 就是把hash值的最后6位作為數(shù)組的下標(biāo)
*/
HashMap<String, String> hashMap2 = new HashMap<>(33);
hashMap2.put("aa", "bbb");
}
//根據(jù)鍵key計(jì)算它的hash值,
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
}