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:语言表达不是很准确,望指正;

相关文章
相关标签/搜索