Map computeIfAbsent computeIfPresent compute merge 方法的运用
前言
本文介绍几个 Map 接口提供的小方法
computeIfAbsent
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
Function ,函数式接口,接受一个输入参数,返回一个结果。
该方法会在不存在指定 key 时,以函数的结果为 value 保存该 key
看一段示例 demo
/**
* 对出现的数字计数
*/
@Test
public void test1() {
Integer[] is = {1, 1, 2, 2, 2, 3, 3, 4};
Map<Integer, Integer> numMap = new HashMap();
for (int i : is) {
if (numMap.containsKey(i)) {
numMap.put(i, numMap.get(i) + 1);
} else {
numMap.put(i, 1);
}
}
numMap.forEach((k, v) -> System.out.println(k +":"+ v));
System.out.println("by use computeIfAbsent");
Map<Integer, Integer> numMap2 = new HashMap();
for (int i : is) {
numMap2.put(i,
numMap2.computeIfAbsent(i, k -> 0) + 1);
}
numMap2.forEach((k, v) -> System.out.println(k +":"+ v));
}
可以看到,使用 computeIfAbsent
会让整个方法简单、清晰
computeIfPresent
default V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue;
if ((oldValue = get(key)) != null) {
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != null) {
put(key, newValue);
return newValue;
} else {
remove(key);
return null;
}
} else {
return null;
}
}
BiFunction,接受两个输入参数的方法,并且返回一个结果。
对于存在的 k,用不为 null 的函数结果值代替,否则移除 k。若 k 不存在,则什么也不干
看 demo
/**
* 只对出现的 1 计数
*/
@Test
public void test2() {
Integer[] is = {1, 1, 2, 2, 2, 3, 3, 4};
Map<Integer, Integer> numMap = new HashMap();
numMap.put(1, 0);
for (int i : is) {
if (i == 1) {
numMap.put(1, numMap.get(1) + 1);
}
}
numMap.forEach((k, v) -> System.out.println(k +":"+ v));
System.out.println("by use computeIfPresent");
Map<Integer, Integer> numMap2 = new HashMap();
numMap2.put(1, 0);
for (int i : is) {
numMap2.computeIfPresent(i,
(k, v) -> ++v);
}
numMap2.forEach((k, v) -> System.out.println(k +":"+ v));
}
compute
default V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue = get(key);
V newValue = remappingFunction.apply(key, oldValue);
if (newValue == null) {
if (oldValue != null || containsKey(key)) {
remove(key);
return null;
} else {
return null;
}
} else {
put(key, newValue);
return newValue;
}
}
跟 computeIfPresent
差不多,就不说明了
merge
default V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
return newValue;
}
跟 computeIfPresent
差不多,唯一的区别是入参多了个 v
,指定 k
不存在时,以传入的 v
存储该 k
总结
Map 提供的这几个方法,在特定场景下可以大幅度优化我们的代码,让整个代码更加优雅、轻便