前言
數組的特點是:尋址容易,插入和刪除困難,數組利用下標定位,時間復雜度為O(1),插入或刪除元素的時間復雜度O(n)。
鏈表的特點是:尋址困難,插入和刪除容易,鏈表定位元素時間復雜度O(n),插入或刪除元素的時間復雜度O(1)。
那么我們能不能綜合兩者的特性,做出一種尋址容易,插入刪除也容易的數據結構?
HashMap是結合兩者優勢,這是一種折中的方案。(在java8中引入了紅黑樹,是對性能的更進一步優化)
HashMap內部結構
HashMap實際上是一個數組,數組里面的每個元素都是一個鏈表。每個元素在通過put方法放入HashMap中的時候,要按照如下步驟進行:
1.根據該元素自身提供的hashcode計算出散列值,該散列值就是數組的下標
2.將新元素放入該數組位置的鏈表中
數組定義:
-
/**
-
* The table, resized as necessary. Length MUST Always be a power of two.
-
*/
-
transient Entry[] table;
這是一個數組,transient關鍵字告訴我們它不會參與序列化。既然是一個數組,總有數目上限,也就意味着如果存入HashMap的元素太多,導致數組大小不能夠存放所有的鏈表的時候,數組大小必須要能夠調整。
Entry是什么類型?

1 static class Entry<K,V> implements Map.Entry<K,V> { 2 final K key; 3 V value; 4 Entry<K,V> next; 5 final int hash; 6 7 /** 8 * Creates new entry. 9 */ 10 Entry(int h, K k, V v, Entry<K,V> n) { 11 value = v; 12 next = n; 13 key = k; 14 hash = h; 15 } 16 .... 17 public final boolean equals(Object o) { 18 if (!(o instanceof Map.Entry)) 19 return false; 20 Map.Entry e = (Map.Entry)o; 21 Object k1 = getKey(); 22 Object k2 = e.getKey(); 23 if (k1 == k2 || (k1 != null && k1.equals(k2))) { 24 Object v1 = getValue(); 25 Object v2 = e.getValue(); 26 if (v1 == v2 || (v1 != null && v1.equals(v2))) 27 return true; 28 } 29 return false; 30 } 31 32 public final int hashCode() { 33 return (key==null ? 0 : key.hashCode()) ^ 34 (value==null ? 0 : value.hashCode()); 35 } 36 ....
這是一個HashMap類的內部靜態類。實現了Map.Entry接口。接受兩個模板參數K和V。key和hash一旦在構造函數中被初始化,就不可改變,並且由於有next的存在,Entry可以構成一個單向鏈表。
HashMap 包含如下幾個構造器:
-
HashMap():構建一個初始容量為 16,負載因子為 0.75 的 HashMap。
-
ashMap(int initialCapacity):構建一個初始容量為 initialCapacity,負載因子為 0.75 的 HashMap。
-
HashMap(int initialCapacity, float loadFactor):以指定初始容量、指定的負載因子創建一個 HashMap。