關於java中的HashMap,咱們在項目中常常使用到,可是咱們的場景是否使用對了呢?java
下面分爲四個部分來闡述個人HashMap的理解設計模式
一、爲何要使用hashMap?數組
在項目中,需求的實現須要使用到一些數據結構來保存key-value形式的數據,也就是說hashMap其實就是一個裝載數據的容器。例如,我須要查詢水果的價格,那麼很天然就會想到將這些數據存放在一個hashMap裏面,蘋果:9.88/kg,雪梨:5/kg,香蕉:5/kg,榴蓮:26/kg,當我問榴蓮的價格的時候,很快就知道了是26/kg。安全
二、hashMap的使用場景有哪些?數據結構
jdk裏面是這麼說的:多線程
Hash table based implementation of the <tt>Map</tt> interface. This
* implementation provides all of the optional map operations, and permits
* <tt>null</tt> values and the <tt>null</tt> key. (The <tt>HashMap</tt>
* class is roughly equivalent to <tt>Hashtable</tt>, except that it is
* unsynchronized and permits nulls.) This class makes no guarantees as to
* the order of the map; in particular, it does not guarantee that the order
* will remain constant over time.
也就是說基於Map接口實現、容許null鍵/值、非同步、不保證有序(好比插入的順序)、也不保證順序不隨時間變化。
當你須要一個效率高,不須要線性安全的map對象的時候,就可使用hashMap
三、源碼(1.7)探索ide
put方法:a)、檢查存放的table是否爲空,若是爲空,則初始化,默認加載因子爲0.75,table初始大小爲16性能
b)、檢查key是否爲空ui
c)、計算key的hash值,確認key在table中的位置this
d)、由於hashMap是由數組+鏈表實現的,須要判斷table[i]中鏈表的元素和key是否相等,找到將老值替換爲新值,而後返回。
e)、若是table[i]的元素爲空,則新增一個元素,當table中的元素大小大於 capacity * loadFactor,則須要調整table的大小了,爲原來的2倍,這個時候會進行數組拷貝,比較耗性能,因此若是初始化容器的時候,能夠確認容器的大小,就最好直接初始化對應的table大小,不須要進行擴容
1 public V put(K key, V value) { 2 if (table == EMPTY_TABLE) { 3 inflateTable(threshold); 4 } 5 if (key == null) 6 return putForNullKey(value); 7 int hash = hash(key); 8 int i = indexFor(hash, table.length); 9 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 10 Object k; 11 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 12 V oldValue = e.value; 13 e.value = value; 14 e.recordAccess(this); 15 return oldValue; 16 } 17 } 18 19 modCount++; 20 addEntry(hash, key, value, i); 21 return null; 22 }
get 方法:和put方法差很少,都是先計算hash值,而後獲取table[i]鏈表中的數據
final Entry<K,V> getEntry(Object key) { if (size == 0) { return null; } int hash = (key == null) ? 0 : hash(key); for (Entry<K,V> 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; }
四、使用的設計模式
無
五、可能會出現的坑
在多線程環境中使用hashMap可能會出現cpu打到100%的異常,就是死循環的狀況,緣由是resize的時候,拷貝對象引用出現循環引用