1.7 hashmap原始碼分析,最近準備面試,整理一下知識點,雖然hashmap的原始碼在網上都已經快翻爛了,但是自己再寫一遍也會加深一下記憶,再走一遍原始碼,就感覺hashmap是自己寫的對不對!
之後我也會分析一下1.8的hashmap的原始碼!好了 屁話不多說,開始我們原始碼分析!
1.基本屬性
static final int default_initial_capacity = 16;//預設容量
static final int maximum_capacity = 1 << 30;//最大容量2的30次冪,超過這個容量用之替換
static final float default_load_factor = 0.75f;//預設負載因子0.75
transient entry table;//entry陣列儲存鍵值對
transient int size; //鍵值對的數量
int threshold; //擴容的閾值 等於負載因子乘以容量
final float loadfactor; //負載因子實際大小
transient int modcount; //hashmap被改變的次數
2.建構函式
public hashmap(int initialcapacity, float loadfactor)
public hashmap(int initialcapacity)
public hashmap()
public hashmap(map m) 4個建構函式最終都會過載第乙個建構函式
3.求hash值
final int hash(object k)
h = hashseed;//隨機hash值
}h ^= k.hashcode();h與物件k的hashcode異或
//這段**叫擾動函式,做了4次移位操作以及4次異或操作
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}**中的擾動函式起到了混合hash值中的高位**與低位**作用,增大了hash值低位的隨機性,,防止hash值低位出現規律性,減少了衝突。
4.求hash值對應陣列座標
static int indexfor(int h, int length) 使用&代替取模,提高效率,也因為這個原因,使得hashmap以二倍擴容,因為陣列長度如果為奇數,length-1就為偶數,末尾就為0,則對應下標取值全部會投影到偶數下標,增大衝突發生的可能,因此 以2的倍數擴容,使得length為偶數,減少衝突發生的次數。
5.get方法
public v get(object key) 如果key為空,則查詢key==null的value ,這也說明了hashmap的key支援為空private v getfornullkey()
return null;
}如果key不為空,先找到entry節點final entry getentry(object key)
return null;
}求key的hash值然後根據hash值找到再table中的下表,返回table節點陣列中的頭節點。
6. put方法
如果key不為空,先定位table陣列下標,如果hash值與table陣列中的某個節點相等,且key也相等,更改value值並返回,如果沒有相等的則插入節點,頭插
public v put(k key, v value)
}modcount++;
addentry(hash, key, value, i);
return null;
}如果 key為空 ,將鍵值對插入table[0]下標處,頭插private v putfornullkey(v value)
}modcount++;
addentry(0, null, value, 0);
return null;
}插入節點時如果大小大於閾值時2倍擴容,
void addentry(int hash, k key, v value, int bucketindex)
createentry(hash, key, value, bucketindex);
}7.擴容方式void resize(int newcapacity)
entry newtable = new entry[newcapacity];
boolean oldalthashing = usealthashing;
usealthashing |= sun.misc.vm.isbooted() &&
(newcapacity >= holder.alternative_hashing_threshold);
boolean rehash = oldalthashing ^ usealthashing;
transfer(newtable, rehash);
table = newtable;
threshold = (int)math.min(newcapacity * loadfactor, maximum_capacity + 1);
}建立2倍容量的新陣列,將舊陣列中的資料重新計算陣列索引加入到新陣列中
HashMap原始碼分析
public hashmap int initialcapacity,float loadfactor 2 接下來是重要的put方法,put方法用於將鍵值對儲存到map中,讓我們來具體分析一下。public v put k key,v value if key null 若key為null,則將va...
HashMap 原始碼分析
1 getentry object key 方法 final entrygetentry object key return null 根據key的hash值計算出索引,得到table中的位置,然後遍歷table處的鍊錶 for entrye table indexfor hash,table.le...
HashMap原始碼分析
public v put k key,v value if key null return putfornullkey value int hash hash key int i indexfor hash,table.length for entrye table i e null e e.nex...