1 7 HashMap原始碼分析

2022-09-23 07:54:10 字數 2585 閱讀 3136

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...