HashMap get方法源码细节分析(JDK1.8)

HashMap get方法源码

get方法图示:
在这里插入图片描述

get方法源码:

get方法

/**
 * 这是一个比较重要的一个方法(get和put方法都是HashMap操作比较重要的方法)
 * 根据键key,获取对应的值
 */
public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

getNode方法

/**
 *  getNode(hash(key), key)
 *  通过key的hash值和key获取节点Node
 */
final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    //将table赋值给tab变量,将table的length赋值给n。tab[(n - 1) & hash]计算存放在数组table中的位置赋值给first。
    //判断该槽位是否为null. first为该槽位的第一个Node。
    if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
        //总是先判断槽位的第一Node是否是我们要获取的Node如果是则直接返回。
        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;//否则返回null
}

getTreeNode方法

/**
 * 获取红黑树的指定节点
 */
final TreeNode<K,V> getTreeNode(int h, Object k) {
    // 从根节点开始查询,判断parent是否为null,为null说明当前节点就是
    // 跟根节点否则调用root()方法需找根节点然后调用find()方法查找节点。
    return ((parent != null) ? root() : this).find(h, k, null);
}

root方法

/**
 * 根据当前节点获取根节点
 */
final TreeNode<K,V> root() {
    //从当前节点开始向上找当前节点的parent
    for (TreeNode<K,V> r = this, p;;) {
        //如果当前节点的parent == null则表示寻找到根节点则返回根节点
        if ((p = r.parent) == null)
            return r;
        //否则将当前节点的父节点赋值给r继续遍历。
        r = p;
    }
}

find方法

/**
 * 这个方法是TreeNode类的一个实例方法,调用该方法的也就是一个TreeNode对象,
 * 该对象就是树上的某个节点,以该节点作为根节点,查找其所有子孙节点,
 * 看看哪个节点能够匹配上给定的键对象
 * h k的hash值
 * k 要查找的对象
 * kc k的Class对象,该Class应该是实现了Comparable<K>的,否则应该是null,参见:
 */
final TreeNode<K,V> find(int h, Object k, Class<?> kc) {
    TreeNode<K,V> p = this;// 把当前对象赋给p,表示当前节点
    do {
        int ph, dir; K pk; // 定义当前节点的hash值、方向(左右)、当前节点的键对象
        TreeNode<K,V> pl = p.left, pr = p.right, q;// 获取当前节点的左孩子、右孩子。定义一个对象q用来存储并返回找到的对象
        if ((ph = p.hash) > h)// 如果当前节点的hash值大于k得hash值h,那么后续就应该让k和左孩子节点进行下一轮比较
            p = pl;// p指向左孩子,紧接着就是下一轮循环了
        else if (ph < h)// 如果当前节点的hash值小于k得hash值h,那么后续就应该让k和右孩子节点进行下一轮比较
            p = pr;// p指向右孩子,紧接着就是下一轮循环了
        else if ((pk = p.key) == k || (k != null && k.equals(pk)))// 如果h和当前节点的hash值相同,并且当前节点的键对象pk和k相等(地址相同或者equals相同)
            return p;// 返回当前节点

        // 执行到这里说明hash比对相同,但是pk和k不相等


        else if (pl == null)//如果左节点为空
            p = pr;// p指向右孩子,紧接着就是下一轮循环
        else if (pr == null)//如果右结点为空
            p = pl;// p指向左孩子,紧接着就是下一轮循环
        // 如果左右孩子都不为空,那么需要再进行一轮对比来确定到底该往哪个方向去深入对比
        // 这一轮的对比主要是想通过comparable方法来比较pk和k的大小
        else if ((kc != null ||
                (kc = comparableClassFor(k)) != null) &&
                (dir = compareComparables(kc, k, pk)) != 0)
            p = (dir < 0) ? pl : pr;// dir小于0,p指向右孩子,否则指向右孩子。紧接着就是下一轮循环
        // 执行到这里说明无法通过comparable比较  或者 比较之后还是相等
        // 从右孩子节点递归循环查找,如果找到了匹配的则返回
        else if ((q = pr.find(h, k, kc)) != null)
            return q;
        else// 如果从右孩子节点递归查找后仍未找到,那么从左孩子节点进行下一轮循环
            p = pl;//进入左节点
    } while (p != null);
    return null;// 未找到,返回null
}

至此get方法及其内部调用的各个方法均讲解完毕。不能在详细了!!!!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值