ConcurrentHashMap 源码分析(二)

一、序言

本文和大家探讨一下 ConcurrentHashMap#get() 方法的源码。

二、源码概览

public V get(Object key) {
    // 定义变量
    Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;

    // 计算键的哈希值
    int h = spread(key.hashCode());

    // 检查哈希表是否为空,并找到键对应的节点
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (e = tabAt(tab, (n - 1) & h)) != null) {

        // 检查节点的哈希值是否与键的哈希值相等
        if ((eh = e.hash) == h) {

            // 检查节点的键是否与给定的键相等,如果相等就返回对应的值
            if ((ek = e.key) == key || (ek != null && key.equals(ek)))
                return e.val;
        }
        // 如果节点的哈希值小于 0,就调用 find 方法来查找节点,
        // 如果找到了就返回对应的值,否则返回 null
        else if (eh < 0)
            return (p = e.find(h, key)) != null ? p.val : null;

        // 遍历链表中的其他节点(如果有的话)
        while ((e = e.next) != null) {

            // 检查节点的键是否与给定的键相等,如果相等就返回对应的值
            if (e.hash == h &&
                ((ek = e.key) == key || (ek != null && key.equals(ek))))
                return e.val;
        }
    }

    // 如果在哈希表中没有找到给定的键,那么就返回 null
    return null;
}

上述代码是 ConcurrentHashMap#get() 方法的源码。

三、源码流程分析

在这里插入图片描述

我们可以分析出 ConcurrentHashMap#get() 的工作流程是:

  1. 首先,通过调用 spread() 方法计算 Hash 值
  2. 然后,检查哈希表和要查找的键所对应的节点是否为 null
  3. 如果不为 null,进一步检查该位置节点的哈希值是否与要查找的键的哈希值相等,如果相等,则直接返回该节点的值。
  4. 如果哈希值不相等,但是该位置节点的哈希值小于 0,说明该位置的节点是红黑树,则调用节点的 find() 方法进行查找,返回对应键的节点。
  5. 如果以上情况都不满足,说明该位置的节点是一个链表结构,则进行链表遍历,查找与给定键相等的节点,找到则返回对应的值。
  6. 如果遍历完链表仍未找到匹配的键,则返回 null。

通过上面的工作流程分析,我们可以总结出其核心流程为:

在这里插入图片描述

  1. 计算出哈希值
  2. 哈希值相等键也相等则直接返回 value
  3. 哈希值小于 0,使用 find() 在红黑树中查找,找到返回 value
  4. 其他情况在链表中查找,找到返回 value
  5. 如果没有找到值就返回 null

往期推荐

  1. ConcurrentHashMap 源码分析(一)
  2. IoC 思想简单而深邃
  3. ThreadLocal
  4. Spring 三级缓存
  5. RBAC 权限设计(二)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值