HashMap(1.8)底層原理之get(key)分析

先上源碼: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:語言表達不是很準確,望指正;

相關文章
相關標籤/搜索