2019-01-06 一種更優雅的方式 replaceAll()
需求:
對map中的所有值統一增減
基礎版本
下面這個方式是可行
的,但是看著不太優雅
public static void main(String[] args) {
Map<Integer, Integer> map = 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) {
Map<Integer, Integer> map = new HashMap<>();
map.forEach((key, value) -> map.merge(key, -1, Integer::sum));
}
}
複製程式碼
關鍵就是map.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;
}
複製程式碼
可以看到如果新值為空就會被移除掉
最佳版本--replaceAll
replaceAll會對map中的所有元素使用傳遞進來的BiFunction進行更新.
public class MapIncr {
public static void main(String[] args) {
Map<Integer, Integer> map = new HashMap<>();
map.replaceAll((k,v)->v+1);
}
}
複製程式碼
總結
- 基礎版本的偏向於指令式程式設計,遍歷map,對map中的每個元素進行處理,處理規則是,這需要使用者說明並編寫整個處理流程.
- 最佳版本則更符合函數語言程式設計,我想替換map中的所有值,替換規則是xxx,隱藏了遍歷邏輯.很明顯,最佳版本的更加清楚明瞭.
- 至於誤用版本,就是對api的錯誤使用了,之所以保留它,只是想說明: keep digging,there is always a better way,