2019-01-06 一种更优雅的方式 replaceAll()
需求:
对map中的所有值统一增减
基础版本
下面这个方式是可行
的,但是看着不太优雅
public static void main(String[] args) { Mapmap = new HashMap<>(); map.forEach((key, value)->map.put(key,map.get(key)-1)); }复制代码
误用版本--merge 有副作用
经过一番研究之后发现了一种简单的方式,但是有个限制 merge之后不能发生结构性修改(也就是map中元素数量不能发生变化)
,在当前场景下只要保证merge后不为空值即可
public class MapIncr { public static void main(String[] args) { Mapmap = new HashMap<>(); map.forEach((key, value) -> map.merge(key, -1, Integer::sum)); }}复制代码
关键就是map.merge()
,源码如下
default V merge(K key, V value, BiFunction 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; }复制代码
可以看到如果新值为空就会被移除掉
最佳版本--replaceAll
replaceAll会对map中的所有元素使用传递进来的BiFunction进行更新.
public class MapIncr { public static void main(String[] args) { Mapmap = new HashMap<>(); map.replaceAll((k,v)->v+1); }}复制代码
总结
- 基础版本的偏向于命令式编程,遍历map,对map中的每个元素进行处理,处理规则是,这需要使用者说明并编写整个处理流程.
- 最佳版本则更符合函数式编程,我想替换map中的所有值,替换规则是xxx,隐藏了遍历逻辑.很明显,最佳版本的更加清楚明了.
- 至于误用版本,就是对api的错误使用了,之所以保留它,只是想说明: keep digging,there is always a better way,