hashmap和concurrenthashmap原始碼分析(1.7/1.8)
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
// 1 判斷老表的容量是否超過最大容量值:如果超過則將閾值設定為 Integer.MAX_VALUE ,並直接返回
// 此時 oldCap * 2 比 Integer.MAX_VALUE 大,因此無法進行重新分佈,只是單純的將閾值擴容到最大
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
// 將 newCap 賦值為 oldCap 的 2 倍,如果 newCap< 最大容量並且 oldCap>=16, 則將新閾值設定為原來的兩倍
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // double threshold : 24
}
//2. 如果老表的容量為 0, 老表的閾值大於 0, 是因為初始容量被放入閾值,則將新表的容量設定為老表的閾值
else if (oldThr > 0)
newCap = oldThr;
else {
//3. 老表的容量為 0, 老表的閾值為 0 ,這種情況是沒有傳初始容量的 new 方法建立的空表,將閾值和容量設定為預設值。
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
// 4. 如果新表的閾值為空 , 則透過新的容量 * 負載因子獲得閾值
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE);
}
// 將當前閾值設定為剛計算出來的新的閾值,定義新表,容量為剛計算出來的新容量,將 table 設定為新定義的表。
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
// 6. 如果老表不為空,則需遍歷所有節點,將節點賦值給新表
if (oldTab != null) {
// 把每個 bucket 都移動到新的 buckets 中
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
if ((e = oldTab[j]) != null) { // 將索引值為 j 的老表頭節點賦值給 e
oldTab[j] = null; // 將老表的節點設定為空 , 以便垃圾收集器回收空間
//7. 如果 e.next 為空 , 則代表老表的該位置只有 1 個節點,外匯跟單gendan5.com計算新表的索引位置 , 直接將該節點放在該位置
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
//8. 如果是紅黑樹節點,則進行紅黑樹的重 hash 分佈 ( 跟連結串列的 hash 分佈基本相同 )
else if (e instanceof TreeNode)
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else {
// 9. 如果是普通的連結串列節點,則進行普通的重 hash 分佈
Node<K,V> loHead = null, loTail = null;// 儲存索引位置為 : “原索引位置”的節點
Node<K,V> hiHead = null, hiTail = null;// 儲存索引位置為 : “原索引位置 +oldCap ”的節點
Node<K,V> next;
do {
next = e.next;
// 如果 e 的 hash 值與老表的容量進行與運算為 0, 則擴容後的索引位置跟老表的索引位置一樣
if ((e.hash & oldCap) == 0) {
if (loTail == null) // 如果 loTail 為空 , 代表該節點為第一個節點
loHead = e; // 則將 loHead 賦值為第一個節點
else
loTail.next = e; // 否則將節點新增在 loTail 後面
loTail = e; // 並將 loTail 賦值為新增的節點
}
// 如果 e 的 hash 值與老表的容量進行與運算為非 0, 則擴容後的索引位置為 : 老表的索引位置+ oldCap
else {
if (hiTail == null) // 如果 hiTail 為空 , 代表該節點為第一個節點
hiHead = e; // 則將 hiHead 賦值為第一個節點
else
hiTail.next = e; // 否則將節點新增在 hiTail 後面
hiTail = e; // 並將 hiTail 賦值為新增的節點
}
} while ((e = next) != null);
// 10. 如果 loTail 不為空(說明老表的資料有分佈到新表上“原索引位置”的節點),則將最後一個節點的 next 設為空,並將新表上索引位置為“原索引位置”的節點設定為對應的頭節點
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
// 11. 如果 hiTail 不為空(說明老表的資料有分佈到新表上“原索引 +oldCap 位置”的節點),則將最後一個節點的 next 設為空,並將新表上索引位置為“原索引 +oldCap ”的節點設定為對應的頭節點
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
//12. 返回新表
return newTab;
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946337/viewspace-2783627/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- HashMap jdk1.7和1.8原始碼剖析HashMapJDK原始碼
- 併發程式設計之ConcurrentHashMap jdk1.7和1.8原始碼剖析程式設計HashMapJDK原始碼
- Java原始碼分析:HashMap 1.8 相對於1.7 到底更新了什麼?Java原始碼HashMap
- JDK1.8 hashMap原始碼分析JDKHashMap原始碼
- HashMap原始碼分析 JDK1.8HashMap原始碼JDK
- 原始碼分析–ConcurrentHashMap與HashTable(JDK1.8)原始碼HashMapJDK
- JDK1.8原始碼分析之HashMapJDK原始碼HashMap
- Jdk1.7下的HashMap原始碼分析JDKHashMap原始碼
- JDK1.8原始碼分析筆記-HashMapJDK原始碼筆記HashMap
- Jdk1.8下的HashMap原始碼分析JDKHashMap原始碼
- 原始碼分析系列1:HashMap原始碼分析(基於JDK1.8)原始碼HashMapJDK
- ConcurrentHashMap (jdk1.7)原始碼學習HashMapJDK原始碼
- JDK1.8 ConcurrentHashMap原始碼閱讀JDKHashMap原始碼
- 併發程式設計之 ConcurrentHashMap(JDK 1.8) putVal 原始碼分析程式設計HashMapJDK原始碼
- Java1.7的HashMap原始碼分析-面試必備技能JavaHashMap原始碼面試
- ConcurrentHashMap 原始碼分析HashMap原始碼
- ConcurrentHashMap基於JDK1.8原始碼剖析HashMapJDK原始碼
- ConcurrentHashMap原始碼刨析(基於jdk1.7)HashMap原始碼JDK
- ConcurrentHashMap 實現原理和原始碼分析HashMap原始碼
- Java HashMap 原始碼逐行解析(JDK1.8)JavaHashMap原始碼JDK
- JDK1.8_HashMap原始碼__tableSizeFor方法解析JDKHashMap原始碼
- Java:這是一份詳細&全面的HashMap 1.7 原始碼分析JavaHashMap原始碼
- 原始碼分析——HashMap原始碼HashMap
- HashMap 原始碼分析HashMap原始碼
- HashMap原始碼分析HashMap原始碼
- 美團面試題:Hashmap的結構,1.7和1.8有哪些區別(史上最深入的分析)面試題HashMap
- HashMap原始碼(JDK1.8)-手動註釋HashMap原始碼JDK
- 一文讀懂JDK1.7,JDK1.8,JDK1.9的hashmap,hashtable,concurrenthashmap及他們的區別JDKHashMap
- 原始碼分析之 HashMap原始碼HashMap
- Java:HashMap原始碼分析JavaHashMap原始碼
- ConcurrentHashMap原始碼分析-JDK18HashMap原始碼JDK
- HashMap1.7與1.8執行緒不安全講解HashMap執行緒
- 集合框架原始碼學習之HashMap(JDK1.8)框架原始碼HashMapJDK
- 原始碼-JDK1.8HashMap擴容方法resize()解析原始碼JDKHashMap
- Java併發包原始碼學習系列:JDK1.8的ConcurrentHashMap原始碼解析Java原始碼JDKHashMap
- 原始碼|jdk原始碼之HashMap分析(一)原始碼JDKHashMap
- 原始碼|jdk原始碼之HashMap分析(二)原始碼JDKHashMap
- HashMap-put原始碼分析HashMap原始碼