JDK8中的compute、computeIfAbsent、computeIfPresent
...大约 3 分钟
写在前面
三个方法的区别:
compute
:计算并更新值computeIfAbsent
:Value
不存在时才计算computeIfPresent
:Value
存在时才计算
computeIfAbsent
不存在时,才会更新,所以只需要传入一个Key
即可,而其他的两个都需要传递一个map
键值对
compute
使用
// map中如果存在 key 则将 value 值+1, 如果不存在则 置为 1
map.compute(cur_sum, (key, value) -> value != null ? value+1 : 1);
源码
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) { // 新值为空
// delete mapping
if (oldValue != null || containsKey(key)) { // 旧值存在时
// 移除该键值
remove(key);
return null;
} else {
// nothing to do. Leave things as they were.
return null;
}
} else { // 新值不为空
// 添加或者覆盖旧值
put(key, newValue);
return newValue;
}
}
computeIfAbsent
使用
// Function<? super K, ? extends V> K是传入类型,V是返回类型
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 11);
map.put(2, 22);
// 传入类型 -> 返回类型
// 如果用不到传入类型,可以直接省略掉
// map.computeIfAbsent(2, 999)
map.computeIfAbsent(2, key -> key+999);
map.computeIfAbsent(3, key -> key+999);
System.out.println(map.get(2));
System.out.println(map.get(3));
源码
/**
* 如果指定的key不存在于映射中,则根据指定的映射函数进行计算并将其放入映射中。
* 如果映射函数返回null,则不执行任何操作,直接返回null。
*
* @param key 要计算新值的key
* @param mappingFunction 根据指定的key计算新值的映射函数
* @return 计算出的新值,如果key已存在于映射中,则返回其对应的旧值;如果映射函数返回null,则返回null
* @throws NullPointerException 如果指定的映射函数为null
*/
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
// 尝试获取key对应的值
if ((v = get(key)) == null) {
V newValue;
// 根据映射函数计算新值
if ((newValue = mappingFunction.apply(key)) != null) {
// 将新值放入映射中
put(key, newValue);
return newValue;
}
}
// 如果key已存在于映射中,则返回其对应的旧值;如果映射函数返回null,则返回null
return v;
}
computeIfPresent
使用
map.computeIfPresent(3, (key, value)-> value+1);
源码
/**
* 如果指定的键存在且其关联的值不为 null,则尝试根据提供的 remappingFunction 对其进行重新映射。
* 如果 remappingFunction 返回非 null 的值,则将其与键关联;如果返回 null,则移除键的映射关系。
* 如果指定的键不存在或其关联的值为 null,则不执行任何操作并返回 null。
*
* @param key 要重新映射的键
* @param remappingFunction 用于重新映射的函数,接受键和其当前关联值作为参数,并返回新的值
* @return 如果指定的键存在且已成功重新映射,则返回新的映射值;如果键不存在或重新映射为 null,则返回 null
* @throws NullPointerException 如果 remappingFunction 为 null
*/
default V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue;
if ((oldValue = get(key)) != null) {
// 通过 remappingFunction 获取新值
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != null) {
// 如果新值不为 null,则用新值替换旧值
put(key, newValue);
return newValue;
} else {
// 如果新值为 null,则移除键的映射关系
remove(key);
return null;
}
} else {
// 如果指定的键不存在或其关联的值为 null,则不执行任何操作并返回 null
return null;
}
}