你只會(huì)用 map.put?試試 Java 8 compute ,操作 Map 更輕松!
今天棧長(zhǎng)分享一個(gè)實(shí)用的 Java 8 開發(fā)技能,那就是 Map 接口中增加的 compute 方法,給 Map 集合計(jì)算更新用的。
compute簡(jiǎn)介
如下所示,Java 8 在 Map 和 ConcurrentMap 接口中都增加了 3 個(gè) compute 方法,說明也是支持多線程并發(fā)安全操作的。
這三個(gè)方法的區(qū)別:
- compute:計(jì)算并更新值
- computeIfAbsent:Value不存在時(shí)才計(jì)算
- computeIfPresent:Value存在時(shí)才計(jì)算
compute有啥用?
話說這有什么卵用?
先看看沒用 Java 8 的一個(gè)小示例:
- /**
- * 公眾號(hào):Java技術(shù)棧
- */
- private static void preJava8() {
- List<String> animals = Arrays.asList("dog", "cat", "cat", "dog", "fish", "dog");
- Map<String, Integer> map = new HashMap<>();
- for(String animal : animals){
- Integer count = map.get(animal);
- map.put(animal, count == null ? 1 : ++count);
- }
- System.out.println(map);
- }
輸出:
{cat=2, fish=1, dog=3}
這是一個(gè)統(tǒng)計(jì)一個(gè)列表中每個(gè)動(dòng)物的數(shù)量,代碼再怎么精簡(jiǎn)都需要一步 get 操作,判斷集合中是否有元素再確定是初始化:1,還是需要 +1。
很多時(shí)候,這個(gè) get 操作顯然是毫無(wú)必要的,所以 Java 8 提供了 3 個(gè) compute 方法,來(lái)看看怎么用吧!
Java 8 compute 實(shí)現(xiàn)方式:
- /**
- * 公眾號(hào):Java技術(shù)棧
- */
- private static void inJava8() {
- List<String> animals = Arrays.asList("dog", "cat", "cat", "dog", "fish", "dog");
- Map<String, Integer> map = new HashMap<>();
- for(String animal : animals){
- map.compute(animal, (k, v) -> v == null ? 1 : ++v);
- }
- System.out.println(map);
- }
使用 compute 方法一行搞定,省去了需要使用 get 取值再判斷的冗余操作,直接就可以獲取元素值并計(jì)算更新,是不是很方便呢?
compute源碼分析
這還是一個(gè)默認(rèn)方法,為什么是默認(rèn)方法,也是為了不改動(dòng)其所有實(shí)現(xiàn)類,關(guān)于默認(rèn)方法的定義可以關(guān)注公眾號(hào)Java技術(shù)棧獲取 Java 8+ 系列教程。
- /**
- * 公眾號(hào):Java技術(shù)棧
- */
- default V compute(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
- // 函數(shù)式接口不能為空
- Objects.requireNonNull(remappingFunction);
- // 獲取舊值
- V oldValue = get(key);
- // 獲取計(jì)算的新值
- V newValue = remappingFunction.apply(key, oldValue);
- if (newValue == null) { // 新值為空
- // delete mapping
- if (oldValue != null || containsKey(key)) { // 舊值存在時(shí)
- // 移除該鍵值
- remove(key);
- return null;
- } else {
- // nothing to do. Leave things as they were.
- return null;
- }
- } else { // 新值不為空
- // 添加或者覆蓋舊值
- put(key, newValue);
- return newValue;
- }
- }
實(shí)現(xiàn)邏輯其實(shí)也很簡(jiǎn)單,其實(shí)就是結(jié)合了 Java 8 的函數(shù)式編程讓代碼變得更簡(jiǎn)單了,Java 也越來(lái)越聰明了。
另外兩個(gè)方法我就不演示了,在特定的場(chǎng)合肯定也肯定特別有用,大家知道就好,需要的時(shí)候要知道拿來(lái)用。
本節(jié)教程所有實(shí)戰(zhàn)源碼已上傳到這個(gè)倉(cāng)庫(kù):
https://github.com/javastacks/javastack
本次的分享就到這里了,希望對(duì)大家有用。覺得不錯(cuò),在看、轉(zhuǎn)發(fā)分享一下哦~