在工程中HashMap使用的非常頻繁,甚至有人說如果只能選擇一個的話我選HashMap。那今天來回顧一下HashMap.
HashMap什麼
首先HashMap繼承自Map<>接口,Map接口的定義了一些方法,比較簡單,不說了
先來看HashMap是如何實現的:
簡單點說HashMap就是一個數組,數組的元素對應着一個鏈表,當鏈表足夠長時轉換爲二叉樹。
首先由幾個很重要的屬性:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 默認容量16 static final int MAXIMUM_CAPACITY = 1 << 30; //最大容量 static final float DEFAULT_LOAD_FACTOR = 0.75f;//重載因子 static final int TREEIFY_THRESHOLD = 8;//轉化樹層級 static final int UNTREEIFY_THRESHOLD = 6;//樹轉回鏈表層級 static final int MIN_TREEIFY_CAPACITY = 64;//最小數容量
首先當我們創建一個HashMap對象,會初始化一個長度爲16的數組。
HashMap<String,String> map = new HashMap<>();
map.put("name","oldma");
當調用put方法,會首先調用hash()方法,並與hash值右移16位進行異或計算
(h = key.hashCode()) ^ (h >>> 16)
驗證結果:得到了一個值!
HashMap<String,String> map = new HashMap<>();
map.put("name","oldma");
System.out.println(Integer.toBinaryString( "name".hashCode()));
System.out.println(Integer.toBinaryString("name".hashCode() >>> 16));
System.out.println( (Integer.toBinaryString("name".hashCode() ^ ("name".hashCode() >>> 16))));
//00110011 01111010 10001011
//00000000 00000000 00110011
//00110011 01111010 10111000
下一步 如果數組爲null n等於初始化數組的長度 16;
重點是(n-1)&hash的方法,n-1結果等於15
00000000 00000000 00001111
&
00110011 01111010 10111000
=
00000000 00000000 00001000 = 15
也就是說第一步右移16位完全是爲了得到後三位是000的值,000&0-15 的結果都是0-15剛好對應長度16的數組下標
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);