1. remove
public V remove(Object key) {
return replaceNode(key, null, null);
}
public boolean remove(Object key, Object value) {
if(key == null)
throw new NullPointerException();
return value != null && replaceNode(key, null, value) != null;
}
final V replaceNode(Object key, V value, Object cv) {
int hash = spread(key.hashCode());
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0 ||
(f = tabAt(tab, i = (n - 1) & hash)) == null)
break;
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
V oldVal = null;
boolean validated = false;
synchronized (f) {
if (tabAt(tab, i) == f) {
if (fh >= 0) {
validated = true;
for (Node<K,V> e = f, pred = null;;) {
K ek;
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
V ev = e.val;
if (cv == null || cv == ev ||
(ev != null && cv.equals(ev))) {
oldVal = ev;
if (value != null)
e.val = value;
else if (pred != null)
pred.next = e.next;
else
setTabAt(tab, i, e.next);
}
break;
}
pred = e;
if ((e = e.next) == null)
break;
}
}
else if (f instanceof TreeBin) {
validated = true;
TreeBin<K,V> t = (TreeBin<K,V>)f;
TreeNode<K,V> r, p;
if ((r = t.root) != null &&
(p = r.findTreeNode(hash, key, null)) != null) {
V pv = p.val;
if (cv == null || cv == pv ||
(pv != null && cv.equals(pv))) {
oldVal = pv;
if (value != null)
p.val = value;
else if (t.removeTreeNode(p))
setTabAt(tab, i, untreeify(t.first));
}
}
}
}
}
if (validated) {
if (oldVal != null) {
if (value == null)
addCount(-1L, -1);
return oldVal;
}
break;
}
}
}
return null;
}
2. clear()
public void clear() {
long delta = 0L;
int i = 0;
Node<K,V>[] tab = table;
while (tab != null && i < tab.length) {
int fh;
Node<K,V> f = tabAt(tab, i);
if (f == null)
++i;
else if ((fh = f.hash) == MOVED) {
tab = helpTransfer(tab, f);
i = 0;
}
else {
synchronized (f) {
if (tabAt(tab, i) == f) {
Node<K,V> p = (fh >= 0 ? f :
(f instanceof TreeBin) ?
((TreeBin<K,V>)f).first : null);
while (p != null) {
--delta;
p = p.next;
}
setTabAt(tab, i++, null);
}
}
}
}
if (delta != 0L)
addCount(delta, -1);
}
3. replace()
- 俩重载函数,区别在于是否需要指定旧值,底层调用 replaceNode()
public V replace(K key, V value) {
if (key == null || value == null)
throw new NullPointerException();
return replaceNode(key, value, null);
}
public boolean replace(K key, V oldValue, V newValue) {
if (key == null || oldValue == null || newValue == null)
throw new NullPointerException();
return replaceNode(key, newValue, oldValue) != null;
}
4. replaceAll
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
if (function == null) throw new NullPointerException();
Node<K,V>[] t;
if ((t = table) != null) {
Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
for (Node<K,V> p; (p = it.advance()) != null; ) {
V oldValue = p.val;
for (K key = p.key;;) {
V newValue = function.apply(key, oldValue);
if (newValue == null)
throw new NullPointerException();
if (replaceNode(key, newValue, oldValue) != null ||
(oldValue = get(key)) == null)
break;
}
}
}
}
5. 小总结
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapTest02 {
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.remove(1): " + concurrentHashMap.remove(1));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("concurrentHashMap.remove(11): " + concurrentHashMap.remove(11));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("concurrentHashMap.remove(11): " + concurrentHashMap.remove(2,2));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("concurrentHashMap.remove(11): " + concurrentHashMap.remove(3, 33));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("concurrentHashMap.replace(4, 40): " + concurrentHashMap.replace(4, 40));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("concurrentHashMap.replace(40, 40): " + concurrentHashMap.replace(40, 40));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("concurrentHashMap.replace(5, 5, 50): " + concurrentHashMap.replace(5, 5, 50));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
System.out.println("concurrentHashMap.replace(6, 60, 60): " + concurrentHashMap.replace(6, 60, 60));
System.out.println("now concurrentHashMap: " + concurrentHashMap);
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("============ 这里新添加了元素 ===========");
for(int i = 11; i <= 23; i++) {
concurrentHashMap.put(i, i);
}
}).start();
System.out.print("被 replaceAll() 执行的元素: ");
concurrentHashMap.replaceAll((key, value) -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(key + " = " + value + "\t");
return value * 10;
});
System.out.println();
System.out.println("concurrentHashMap.replaceAll((key, value) -> value * 10 )后, now concurrentHashMap: " + concurrentHashMap);
concurrentHashMap.clear();
System.out.println("concurrentHashMap.clear()后, now concurrentHashMap: \n" + concurrentHashMap);
}
}
- 可以看到,在进行 replaceAll() 执行替换时,新添加的元素中,[index, tab.length) 位置的元素进行了替换,具体可回看 内部类Traverser 的 advance()方法。(02篇)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/24bb453fa843e4617c5044c4174d5a7e.png)