HashMap是Java集合框架中常見的一種數據結構,它提供了快速存儲、查找和刪除元素的能力。它是由數組和鏈表實現的鍵值對,通過哈希算法來快速定位數組下標,避免了遍歷整個數組來查找元素的低效率問題。
一、HashMap基本概念
在了解HashMap的實現原理之前,需要掌握HashMap的基本概念。
1. HashMap的鍵值對
HashMap的元素由鍵和值組成,稱為鍵值對。HashMap中的鍵和值必須都是對象才能被存儲。通常使用String作為鍵。
2. 哈希算法
哈希算法是通過將任意長度的數據映射為固定長度的數據,通常是一個較小的整數值,稱為哈希值。哈希值可以快速地用於查找數組或其他數據結構中的數據,提高數據的訪問效率。
3. 鍵的唯一性
HashMap中的鍵是唯一的。如果向HashMap中添加元素時,鍵已經存在,那麼該元素的值將會覆蓋掉原有的值。如果元素的值為null,則鍵可以重複。
二、HashMap的實現原理
HashMap是由數組和鏈表組成的鍵值對,每個鍵值對稱為一個Entry對象。HashMap的核心就是通過哈希算法,將鍵值對存儲到數組的不同位置中,然後通過鏈表將相同下標的元素串起來。
三、HashMap的put方法實現原理
put方法是HashMap中的核心操作,用於向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 (Entry e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
在這個put方法中,有三個變量需要了解:
1. hash:通過hashCode()方法計算的鍵的哈希值。
2. i:計算出的鍵值對將要存儲的位置。
3. table:數組,用於存儲鍵值對。
put方法實現的流程如下:
1. 判斷鍵是否為null,如果是,直接調用putForNullKey方法,將值保存到map中,然後返回值。
2. 通過hash方法計算鍵的哈希值,然後通過indexFor方法計算出在table數組中的位置。
3. 從table數組中取出對應位置的元素,並遍歷這個元素的鏈表,查找是否有相同key的元素。
4. 如果找到了相同key的元素,則將新的值賦給元素的value,並返回原有的value。
5. 如果在鏈表中沒有找到相同key的元素,則將新的值添加到鏈表的最前面。
四、HashMap的get方法實現原理
get方法是用於獲取HashMap中指定鍵的值。其實現方式如下:
public V get(Object key) { if (key == null) return getForNullKey(); Entry entry = getEntry(key); return null == entry ? null : entry.getValue(); } final Entry getEntry(Object key) { int hash = (key == null) ? 0 : hash(key); for (Entry e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } return null; }
在這個get方法中,有三個變量需要了解:
1. hash:通過hashCode()方法計算的鍵的哈希值。
2. i:計算出的鍵值對在table數組中的位置。
3. table:數組,用於存儲鍵值對。
get方法實現的流程如下:
1. 如果鍵為null,則直接調用getForNullKey 方法獲取值。
2. 通過哈希算法和indexFor方法查找元素在table數組中的位置。
3. 從table數組中取出對應位置的元素,並遍歷這個元素的鏈表,查找是否有相同的鍵,如果找到了,則返回對應的value。
4. 如果在鏈表中沒有找到相同key的元素,則返回null。
五、HashMap的容量和負載因子
HashMap的容量和負載因子是指table數組的長度和鍵值對個數之比。
當鍵值對的個數達到容量和負載因子的乘積時,就需要對table進行擴容。同時,在擴容時,需要將現有的元素重新哈希,然後存儲到新的table數組中。
在HashMap中,負載因子默認為0.75,即當鍵值對的個數達到75%的容量時,進行擴容。這是基於將數組長度設置為2的冪的算法,確保哈希鏈表的最大長度為8位,從而提高了查找和插入元素的效率。
六、HashMap的使用場景
HashMap適用於需要快速查找、插入、刪除數據的場景。由於其底層是基於數組和鏈表實現的,因此處理大量數據時,執行效率較高。尤其是在需要頻繁遍曆元素的場景下,與傳統的數組和鏈表相比,其查找效率更高。
七、HashMap的例子
以下是一個簡單的HashMap例子,用於存儲人名和年齡:
public class HashMapExample { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); map.put("Tom", 30); map.put("Jerry", 25); map.put("Mike", 28); map.put("Lucy", 33); System.out.println("Tom's age is " + map.get("Tom")); // Tom's age is 30 map.remove("Lucy"); System.out.println("Map contains Lucy? " + map.containsKey("Lucy")); // Map contains Lucy? false for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + " is " + entry.getValue() + " years old."); } } }
在這個例子中,我們創建了一個HashMap對象,並將四對鍵值對(人名和年齡)保存到HashMap中。然後通過get方法獲取Tom的年齡,再使用remove方法刪除Lucy,最後使用entrySet方法遍歷Map的所有元素,並輸出人名和年齡。
八、總結
本文探討了HashMap的原理和實現方式。我們深入了解了HashMap的數據結構,介紹了其put方法和get方法的實現原理,還介紹了HashMap的容量、負載因子以及使用場景。
HashMap在Java中使用廣泛,它提供了快速存儲、查找和刪除元素的能力,避免了遍歷整個數組來查找元素的低效率問題。相信通過本文的介紹,讀者能夠更全面地了解HashMap,並在實際開發中更加靈活地使用HashMap。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/244466.html