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