先上源碼:node
public V get(Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; }
咱們都知道hashMap底層數據結構爲:數組+單項鍊表+紅黑樹;算法
獲取一個value值首先要獲取當前key值所在的節點,獲得該節點 e.value屬性值即爲目標值;數組
第一步:對key值進行hash運算,獲得節點位置;(如何hash運算:獲取key值得hashcode將其稱爲h值,而後對該h值>>>16無符號右移16將其稱爲h16,而後對這兩個值進行異或運算 h^h16)。hash運算要通過三個步驟才能算出節點位置。數據結構
第二部:getNode(h,key); 有告終點位置,咱們就能夠進行下一步的運算;h即爲數組的下標;spa
final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }
這個方法中有5個局部變量:code
Node<K,V>[] tab;//hashmap中數組get
Node<K,V> first, e;//目標節點的第一個元素、目標節點元素源碼
int n; //數組長度hash
K k;//目標節點的key值table
爲何要傳兩個值(int hash, Object key):存在hash衝突!
第一個if判斷:知足三個條件 ->數組不爲空 && 數組長度>0 && 目標節點存在 ;
若是知足這三個條件,能夠獲得一個數組元素,目標值即存在該元素之中;
第二個if判斷:知足兩個調節-> 第一個元素節點的下標與目標節點的下標一致&&key值一致;
這種狀況存在當前數組元素只有一個節點,直接返回該數組元素值;
第三個if判斷:第二if不知足時,表示該值存在一個鏈表中;
首先判斷當前結點是否爲紅黑樹,若是是紅黑樹,則進行紅黑樹取值操做;
若是是鏈表,便利鏈表獲取目標值;
總結:hashmap底層是數組+鏈表+紅黑樹;獲取value值總而言之就是經過key值hash運算、無符號位移運算以及異或運算得到數組下表位置;
獲得數組元素目標數據以後,便可獲得一個鏈表,判斷該鏈表第一個節點值是否爲所求值,若是是直接返回,不是的話判斷是否爲紅黑樹,若是是紅黑樹,
紅黑樹算法遍歷求值;非紅黑樹,則do...while遍歷鏈表;
ps:語言表達不是很準確,望指正;