CONCURRENT中的get方法
public V get(Object key) {
//tab 引用map.table
//e 当前元素
//p 目标节点
//n table数组长度
//eh 当前元素hash
//ek 当前元素key
Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
//扰动运算后得到 更散列的hash值
int h = spread(key.hashCode());
//条件一:(tab = table) != null
//true->表示已经put过数据,并且map内部的table也已经初始化完毕
//false->表示创建完map后,并没有put过数据,map内部的table是延迟初始化的,只有第一次写数据时会触发创建逻辑。
//条件二:(n = tab.length) > 0 true->表示table已经初始化
//条件三:(e = tabAt(tab, (n - 1) & h)) != null
//true->当前key寻址的桶位 有值
//false->当前key寻址的桶位中是null,是null直接返回null
if ((tab = table) != null && (n = tab.length) > 0 &&
(e = tabAt(tab, (n - 1) & h)) != null) {
//前置条件:当前桶位有数据
//对比头结点hash与查询key的hash是否一致
//条件成立:说明头结点与查询Key的hash值 完全一致
if ((eh = e.hash) == h) {
//完全比对 查询key 和 头结点的key
//条件成立:说明头结点就是查询数据
if ((ek = e.key) == key || (ek != null && key.equals(ek)))
return e.val;
}
//条件成立:
//1.-1 fwd 说明当前table正在扩容,且当前查询的这个桶位的数据 已经被迁移走了
//2.-2 TreeBin节点,需要使用TreeBin 提供的find 方法查询。
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;
}
}
return null;
}
然后就来到了ForwardingNode的find(int h, Object k)
Node<K,V> find(int h, Object k) {
// loop to avoid arbitrarily deep recursion on forwarding nodes
//tab 一定不为空
Node<K,V>[] tab = nextTable;
outer: for (;;) {
//n 表示为扩容而创建的 新表的长度
//e 表示在扩容而创建新表使用 寻址算法 得到的 桶位头结点
Node<K,V> e; int n;
//条件一:永远不成立
//条件二:永远不成立
//条件三:永远不成立
//条件四:在新扩容表中 重新定位 hash 对应的头结点
//true -> 1.在oldTable中 对应的桶位在迁移之前就是null
// 2.扩容完成后,有其它写线程,将此桶位设置为了null
if (k == null || tab == null || (n = tab.length) == 0 ||
(e = tabAt(tab, (n - 1) & h)) == null)
return null;
//前置条件:扩容后的表 对应hash的桶位一定不是null,e为此桶位的头结点
//e可能为哪些node类型?
//1.node 类型
//2.TreeBin 类型
//3.FWD 类型
for (;;) {
//eh 新扩容后表指定桶位的当前节点的hash
//ek 新扩容后表指定桶位的当前节点的key
int eh; K ek;
//条件成立:说明新扩容 后的表,当前命中桶位中的数据,即为 查询想要数据。
if ((eh = e.hash) == h &&
((ek = e.key) == k || (ek != null && k.equals(ek))))
return e;
//eh<0
//1.TreeBin 类型 2.FWD类型(新扩容的表,在并发很大的情况下,可能在此方法 再次拿到FWD类型..)
if (eh < 0) {
if (e instanceof ForwardingNode) {
tab = ((ForwardingNode<K,V>)e).nextTable;
continue outer;
}
else
//说明此桶位 为 TreeBin 节点,使用TreeBin.find 查找红黑树中相应节点。
return e.find(h, k);
}
//前置条件:当前桶位头结点 并没有命中查询,说明此桶位是 链表
//1.将当前元素 指向链表的下一个元素
//2.判断当前元素的下一个位置 是否为空
// true->说明迭代到链表末尾,未找到对应的数据,返回Null
if ((e = e.next) == null)
return null;
}
}
}