推荐阅读时间:5分钟
简介
本篇接上篇 Java 8 HashMap (上)—— 红黑树,
继续探讨 Java8 的HashMap 的新特性。内容不多,重点介绍 compute 方法。
compute
compute 方法主要用来将一个复杂计算的结果作为值赋给指定的键。key 指待修改或插入的键,remappingFunction 是一个 BiFunction 对象。
BiFunction 是指一个 二元(binary)函数;定义时,指定两个入参字段类型和一个结果字段类型。通过实现 apply 方法来自定义计算逻辑。
BiFunction 部分源码如下:1
2
3
4
5
6
7
8
9
10
11public interface BiFunction<T, U, R> {
/**
* Applies this function to the given arguments.
*
* @param t the first function argument
* @param u the second function argument
* @return the function result
*/
R apply(T t, U u);
}
compute 方法源码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
if (remappingFunction == null)
throw new NullPointerException();
int hash = hash(key);
Node<K,V>[] tab; Node<K,V> first; int n, i;
int binCount = 0;
TreeNode<K,V> t = null;
Node<K,V> old = null;
if (size > threshold || (tab = table) == null ||
(n = tab.length) == 0)
n = (tab = resize()).length;
//根据 key 值,找到对应的 旧值
if ((first = tab[i = (n - 1) & hash]) != null) {
if (first instanceof TreeNode)
old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);
else {
Node<K,V> e = first; K k;
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
old = e;
break;
}
++binCount;
} while ((e = e.next) != null);
}
}
V oldValue = (old == null) ? null : old.value;
//计算出新值
V v = remappingFunction.apply(key, oldValue);
if (old != null) {
if (v != null) {
old.value = v;
afterNodeAccess(old);
}
else
//如果新值为 null,删掉这个 Node
removeNode(hash, key, null, false, true);
}
//如果新值不为 null,替换这个 Node
else if (v != null) {
if (t != null)
t.putTreeVal(this, tab, hash, key, v);
else {
tab[i] = newNode(hash, key, v, first);
if (binCount >= TREEIFY_THRESHOLD - 1)
treeifyBin(tab, hash);
}
++modCount;
++size;
afterNodeInsertion(true);
}
return v;
}
computeIfAbsent、computeIfPresent 方法与 compute 类似,分别表示当相应键的值缺席、存在时,才进行 compute 方法。
源码与 compute 基本一致,不赘述。
demo 如下:
1 | public static void main(String[] args) { |
结果:1
{k1=test_k1_v1, k2=v2, k3=test_k3_v3, k11=test_k11_null, k21=test_k21}
merge
merge 方法是根据旧值进行计算,修改相应 Node。与 compute 结构相似,不过 BiFunction 入参为 oldValue,newValue。
源码与 compute 基本一致,不赘述。
其他
其他新增的方法如下:
1 |
|
- getOrDefault 方法根据 key 获取相应的值,如果为 null,则返回设置的默认值。
- putIfAbsent 方法会在 指定的 key 不存在时,插入相应的值。
- remove(Object key, Object value) 方法会根据 key 和 value 进行删除,如果 相应 key 的值不为该 value,则不执行删除并返回 false。
- replace(K key, V oldValue, V newValue) 与 replace(K key, V value) 都是替换值的操作,具体区别与上述方法类似。
最后
HashMap历时一个半月,终于告一段落了😂。
由于在源码分析系列含有大量代码,放在公众号上不方便阅读,后续写的话会发在博客上。有兴趣的欢迎访问 http://jasonsonghoho.github.io 。
“你不知
这风雪一程
有太多不易”