1. 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()); // 获得 hash 值
/* tab 不为 null && tab数组长度 > 0 && tab对应桶位不为空 */
if ((tab = table) != null && (n = tab.length) > 0 &&
(e = tabAt(tab, (n - 1) & h)) != null) {
/* e 为 key 对应的节点 */
if ((eh = e.hash) == h) {
if ((ek = e.key) == key || (ek != null && key.equals(ek)))
return e.val;
}
/* 转移节点 or 树节点 or 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;
}
}
return null; // 未找到返回 null
}
2. getOrDefault
- 获取到则返回 value,获取不到(即 null) 返回指定的默认值
public V getOrDefault(Object key, V defaultValue) {
Vv;
return (v = get(key)) == null ? defaultValue : v;
}
3. compute
-
给定 key 值找到节点 p,与 remappingFunction(key, value) 生成的 val 值
- p 为 null,val 为null :没有改变,相当于无需进行操作
- p 为 null,val 不为null :新添加节点 Node(key, val)
- p 不为 null,val 为null :相当于删除 key 对应的节点
- p 不为 null,val 不为null :相当于更换 p 的 value 值
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
/* null 异常检测 */
if (key == null || remappingFunction == null)
throw new NullPointerException();
/* 获取 hash 值 */
int h = spread(key.hashCode());
V val = null;
int delta = 0; // 对应的 count 变化计数
int binCount = 0; // 当前桶位的节点个数计数,用于判断链表是否需要树化
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
/* tab 还未初始化 */
if (tab == null || (n = tab.length) == 0)
tab = initTable();
/* 对应的桶位节点为 null */
else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
/* CAS设置 tab[i] 的值为 r */
if (casTabAt(tab, i, null, r)) {
binCount = 1;
Node<K,V> node = null;
try {
/* 若 val 为null,不 new 新节点,因为 ConcurrentHashMap 的 key,value 都不能为 null*/
if ((val = remappingFunction.apply(key, null)) != null) {
delta = 1;
node = new Node<K,V>(h, key, val, null);
}
} finally {
setTabAt(tab, i, node); // 设置桶位首节点
}
}
}
/* binCount == 0 代表当前位置已被其他线程设置值 */
if (binCount != 0)
break;
}
/* 当前tab正在扩容,先帮助扩容 */
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
synchronized (f) {
if (tabAt(tab, i) == f) {
/* 链表节点 */
if (fh >= 0) {
binCount = 1;
for (Node<K,V> e = f, pred = null;; ++binCount) {
K ek;
/* 找到 key 对应的节点 */
if (e.hash == h &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
val = remappingFunction.apply(key, e.val);
/* 若 val 不为null,相当于更改节点的value值 */
if (val != null)
e.val = val;
else {
/* 若 val 为null,相当于删除该节点 */
delta = -1;
Node<K,V> en = e.next;
if (pred != null)
pred.next = en;
else
setTabAt(tab, i, en);
}
break;
}
pred = e;
/*找不到key对应的节点,若 val 不为null,添加一个节点 */
if ((e = e.next) == null) {
val = remappingFunction.apply(key, null);
if (val != null) {
delta = 1;
pred.next =
new Node<K,V>(h, key, val, null);
}
break;
}
}
}
/* 树节点 */
else if (f instanceof TreeBin) {
binCount = 1;
TreeBin<K,V> t = (TreeBin<K,V>)f;
TreeNode<K,V> r, p;
if ((r = t.root) != null)
p = r.findTreeNode(h, key, null);
else
p = null;
V pv = (p == null) ? null : p.val;
val = remappingFunction.apply(key, pv);
/* val 不为null,找到节点p则替换value值,找不到则添加节点 */
if (val != null) {
if (p != null)
p.val = val;
else {
delta = 1;
t.putTreeVal(h, key, val);
}
}
/* val 为null,相当于删除节点 */
else if (p != null) {
delta = -1;
if (t.removeTreeNode(p))
setTabAt(tab, i, untreeify(t.first));
}
}
}
}
/* binCount > 默认树化节点=8 则进行树化 */
if (binCount != 0) {
if (binCount >= TREEIFY_THRESHOLD)
treeifyBin(tab, i);
break;
}
}
}
/* delta 不为0,则进行对应count计数,删除的 delta 为负数 */
if (delta != 0)
addCount((long)delta, binCount);
return val;
}
4. computeIfAbsent
-
给定 key 值找到节点 p,与 remappingFunction(key) 生成的 val 值
- p 为 null,val 为null :没有改变,相当于无需进行操作
- p 为 null,val 不为null :新添加节点 Node(key, val)
- p 不为 null,val 为null :返回 val 值
- p 不为 null,val 不为null :返回 val 值
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
/* null 异常检测 */
if (key == null || mappingFunction == null)
throw new NullPointerException();
int h = spread(key.hashCode()); // 获取 hash 值
V val = null;
int binCount = 0;
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
/* tab 未初始化 */
if (tab == null || (n = tab.length) == 0)
tab = initTable();
/* 对应的桶位节点为 null */
else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
/* CAS设置 tab[i] 的值为 r */
if (casTabAt(tab, i, null, r)) {
binCount = 1;
Node<K,V> node = null;
/* 若val不为null,新添加一个节点,并将该节点设置为桶位首节点 */
try {
if ((val = mappingFunction.apply(key)) != null)
node = new Node<K,V>(h, key, val, null);
} finally {
setTabAt(tab, i, node);
}
}
}
/* 若 binCount == 0 代表 CAS 设置失败 */
if (binCount != 0)
break;
}
/* 若当前tab正在扩容,先帮助扩容 */
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
boolean added = false;
synchronized (f) {
/* 加锁后先判断 首节点f 有没有被修改 */
if (tabAt(tab, i) == f) {
/* 链表节点 */
if (fh >= 0) {
binCount = 1;
for (Node<K,V> e = f;; ++binCount) {
K ek; V ev;
/* e 为key对应的节点,修改 e 的 value 值 */
if (e.hash == h &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
val = e.val;
break;
}
Node<K,V> pred = e;
/* 找不到key对应的节点,val不为 null 则在末尾添加新节点 */
if ((e = e.next) == null) {
if ((val = mappingFunction.apply(key)) != null) {
added = true;
pred.next = new Node<K,V>(h, key, val, null);
}
break;
}
}
}
/* 树节点 */
else if (f instanceof TreeBin) {
binCount = 2;
TreeBin<K,V> t = (TreeBin<K,V>)f;
TreeNode<K,V> r, p;
/* 找到节点p,替换value值 */
if ((r = t.root) != null &&
(p = r.findTreeNode(h, key, null)) != null)
val = p.val;
/* 若 p为 null && val 不为null,添加新节点 */
else if ((val = mappingFunction.apply(key)) != null) {
added = true;
t.putTreeVal(h, key, val);
}
}
}
}
if (binCount != 0) {
/* 元素个数 > 树化默认值= 8,进行树化操作 */
if (binCount >= TREEIFY_THRESHOLD)
treeifyBin(tab, i);
/* 若未发生添加操作,返回 val */
if (!added)
return val;
break;
}
}
}
/* 执行到这里代表 added 为true,val 不为null代表新添加了一个节点 */
if (val != null)
addCount(1L, binCount);
return val;
}
5. computeIfPresent
-
给定 key 值找到节点 p,与 remappingFunction(key,value) 生成的 val 值
- p 为 null :不进行任何操作
- p 不为 null,val 为null :删除 p 节点
- p 不为 null,val 不为null :替换 p 节点的 value 值
public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
/* null 异常检测 */
if (key == null || remappingFunction == null)
throw new NullPointerException();
int h = spread(key.hashCode()); // 获取 hash 值
V val = null;
int delta = 0;
int binCount = 0;
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
/* tab 未初始化 */
if (tab == null || (n = tab.length) == 0)
tab = initTable();
/* 当前桶位为空,直接退出 */
else if ((f = tabAt(tab, i = (n - 1) & h)) == null)
break;
/* 当前tab正在扩容,先帮助扩容 */
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
synchronized (f) {
/* 锁住节点后判断 首节点f 有没有被修改 */
if (tabAt(tab, i) == f) {
/* 链表节点 */
if (fh >= 0) {
binCount = 1;
for (Node<K,V> e = f, pred = null;; ++binCount) {
K ek;
/* 找到 key 对应的节点 */
if (e.hash == h &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
val = remappingFunction.apply(key, e.val);
/* val 不为null,替换 value 值,若为null,删除该节点 */
if (val != null)
e.val = val;
else {
delta = -1;
Node<K,V> en = e.next;
if (pred != null)
pred.next = en;
else
setTabAt(tab, i, en);
}
break;
}
pred = e;
if ((e = e.next) == null)
break;
}
}
/* 树节点 */
else if (f instanceof TreeBin) {
binCount = 2;
TreeBin<K,V> t = (TreeBin<K,V>)f;
TreeNode<K,V> r, p;
/* 找到 key 对应的节点 */
if ((r = t.root) != null &&
(p = r.findTreeNode(h, key, null)) != null) {
val = remappingFunction.apply(key, p.val);
/* val 不为null,替换 value 值,若为null,删除该节点 */
if (val != null)
p.val = val;
else {
delta = -1;
if (t.removeTreeNode(p))
setTabAt(tab, i, untreeify(t.first));
}
}
}
}
}
if (binCount != 0)
break;
}
}
/* 发生了删除操作,count进行相应的计数 */
if (delta != 0)
addCount((long)delta, binCount);
return val;
}
6. 小总结
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapTest03 {
public static void main(String[] args) throws Exception {
ConcurrentHashMap<Integer, Integer> concurrentHashMap = new ConcurrentHashMap<>();
for(int i = 1; i <= 10; i++) {
concurrentHashMap.put(i, i);
}
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("concurrentHashMap.get(1): " + concurrentHashMap.get(1));
System.out.println("concurrentHashMap.get(11): " + concurrentHashMap.get(11));
System.out.println("concurrentHashMap.getOrDefault(1, 10): " + concurrentHashMap.getOrDefault(1, 10));
System.out.println("concurrentHashMap.getOrDefault(11, 11): " + concurrentHashMap.getOrDefault(11, 11));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("=================== compute =======================");
System.out.println("concurrentHashMap.compute(1, (key, value) -> value * 10): " + concurrentHashMap.compute(1, (key, value) -> value * 10));
System.out.println("concurrentHashMap.compute(2, (key, value) -> null): " + concurrentHashMap.compute(2, (key, value) -> null));
/* 这里很坑爹,因为当前桶位为空时,执行的是 val = remappingFunction.apply(key, null)) != null
* 可以看到value值出变成null,即当使用value值进行操作时,会报 null 异常 */
System.out.println("concurrentHashMap.compute(11, (key, value) -> 110): " + concurrentHashMap.compute(11, (key, value) -> 110));
System.out.println("concurrentHashMap.compute(12, (key, value) -> null): " + concurrentHashMap.compute(12, (key, value) -> null));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("=================== computeIfAbsent =======================");
System.out.println("concurrentHashMap.computeIfAbsent(3, (key) -> 30): " + concurrentHashMap.computeIfAbsent(3, (key) -> 30));
System.out.println("concurrentHashMap.computeIfAbsent(4, (key) -> null): " + concurrentHashMap.computeIfAbsent(4, (key) -> null));
System.out.println("concurrentHashMap.computeIfAbsent(13, (key) -> 130): " + concurrentHashMap.computeIfAbsent(13, (key) -> 130));
System.out.println("concurrentHashMap.computeIfAbsent(14, (key) -> null): " + concurrentHashMap.computeIfAbsent(14, (key) -> null));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("=================== computeIfPresent =======================");
System.out.println("concurrentHashMap.computeIfPresent(5, (key, value) -> value * 10): " + concurrentHashMap.computeIfPresent(5 (key, value) -> value * 10));
System.out.println("concurrentHashMap.computeIfPresent(6, (key, value) -> null): " + concurrentHashMap.computeIfPresent(6, (key, value) -> null));
System.out.println("concurrentHashMap.computeIfPresent(15, (key, value) -> value * 10): " + concurrentHashMap.computeIfPresent(15, (key, value) -> value * 10));
System.out.println("concurrentHashMap.computeIfPresent(16, (key, value) -> null): " + concurrentHashMap.computeIfPresent(16, (key, value) -> null));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
}
}
版权声明:本文为weixin_44245828原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。