jdk-map-hashMap

  關於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的時候,拷貝對象引用出現循環引用

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息