HashMap作為Java中最常用的集合之一,具有快速的查找和插入性能,其put方法在HashMap中扮演着至關重要的角色。本文將從多個方面詳細介紹HashMap put方法的內部實現,幫助讀者深入理解其工作原理。
一、概述
HashMap是基於哈希表實現的,它通過將元素的鍵hash為一個整型值來實現快速查找。put方法是HashMap中用於插入元素的核心方法之一,在使用HashMap時,了解put方法的工作原理非常必要。
二、實現原理
在了解HashMap put方法的具體實現之前,需要先掌握一些HashMap的基礎知識:
HashMap是由一個數組和鏈表組成的,數組中的每個元素又是一個鏈表。
當我們向HashMap中插入一個元素時,會先通過hash函數對元素的鍵進行哈希處理,將得到的哈希值作為數組下標,將元素存儲在對應的數組位置。如果相同哈希值的元素不止一個,那麼這些元素就會被插入到同一個鏈表中。
下面是HashMap put方法的核心源代碼:
public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node[] tab; Node p; int n, i; // 判斷是否需要初始化哈希表 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); else {//有節點,遍歷鏈表 Node e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode)//節點類型為樹節點 e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value); else {//節點類型為鏈表節點 for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); //鏈表長度超過閾值,轉為樹結構 if (binCount >= TREEIFY_THRESHOLD - 1)//(樹化條件1) treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break;//查找到對應節點 p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize();//擴容 afterNodeInsertion(evict); return null; }
整個方法的主體流程如下:
- 通過hash函數計算出元素鍵對應的哈希值;
- 判斷哈希表是否初始化,若未初始化則進行初始化;
- 計算數組下標,將元素插入數組對應位置的鏈表中:
- 如果該位置沒有元素,則直接插入;
- 如果該位置已有元素,則從鏈表頭開始遍歷鏈表,查找是否存在相同鍵的元素:
- 如果查找到相同鍵的元素,直接替換其值;
- 如果未查找到相同鍵的元素,則將該元素插入鏈表尾部。
- 檢查鏈表長度,若鏈表長度超過閾值,則將鏈錶轉化為樹;
- 檢查是否需要擴容哈希表,若需要則進行擴容;
- 執行插入後後續操作,如回調用戶函數、更新size等操作。
三、參數
在使用HashMap put方法時,有幾個參數需要注意:
1、key
HashMap中的鍵必須是不可變對象,例如String或Integer等類的實例。如果使用可變對象作為鍵,可能會導致無法查找和訪問鍵對應的值,甚至會導致內存泄漏。
2、value
value參數是我們要插入的元素值。與key一樣,value也應該是不可變對象。如果value是可變對象,則在插入後修改該對象可能會導致HashMap中元素的值混亂。
3、onlyIfAbsent
該參數用於控制是否只在當前HashMap中不存在指定鍵的情況下才插入指定鍵值對,若值為true則只在鍵不存在時插入,否則直接替換原有值。
4、evict
該參數指定當前HashMap是否可以移除元素,若值為true則可以移除,否則不可移除。若需要保證元素不被移除,則可以將該參數設為false。
四、總結
本文介紹了HashMap put方法的原理、源代碼和相關參數,希望通過閱讀本文,讀者能夠深入理解HashMap的內部機制,並在實際開發中靈活使用該數據結構。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/201050.html