你只會用 map.put?試試 Java 8 compute ,操作 Map 更輕鬆!

Java技術棧發表於2021-03-15

今天棧長分享一個實用的 Java 8 開發技能,那就是 Map 介面中增加的 compute 方法,給 Map 集合計算更新用的。

compute簡介

如下所示,Java 8 在 Map 和 ConcurrentMap 介面中都增加了 3 個 compute 方法,說明也是支援多執行緒併發安全操作的。

這三個方法的區別:

  • compute:計算並更新值
  • computeIfAbsent:Value不存在時才計算
  • computeIfPresent:Value存在時才計算

compute有啥用?

話說這有什麼卵用?

先看看沒用 Java 8 的一個小示例:

/**
* 公眾號:Java技術棧
*/
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}

這是一個統計一個列表中每個動物的數量,程式碼再怎麼精簡都需要一步 get 操作,判斷集合中是否有元素再確定是初始化:1,還是需要 +1。

很多時候,這個 get 操作顯然是毫無必要的,所以 Java 8 提供了 3 個 compute 方法,來看看怎麼用吧!

Java 8 compute 實現方式:

/**
* 公眾號:Java技術棧
*/
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 取值再判斷的冗餘操作,直接就可以獲取元素值並計算更新,是不是很方便呢?

compute原始碼分析

這還是一個預設方法,為什麼是預設方法,也是為了不改動其所有實現類,關於預設方法的定義可以關注公眾號Java技術棧獲取 Java 8+ 系列教程。

/**
* 公眾號:Java技術棧
*/
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;
    }
}

實現邏輯其實也很簡單,其實就是結合了 Java 8 的函數語言程式設計讓程式碼變得更簡單了,Java 也越來越聰明瞭。

另外兩個方法我就不演示了,在特定的場合肯定也肯定特別有用,大家知道就好,需要的時候要知道拿來用。

本節教程所有實戰原始碼已上傳到這個倉庫:

https://github.com/javastacks/javastack

本次的分享就到這裡了,希望對大家有用。覺得不錯,在看、轉發分享一下哦~

最後,Java 8 系列教程還會繼續更新,關注Java技術棧公眾號第一時間推送,還可以在公眾號選單中獲取歷史 Java 教程,都是乾貨。

版權申明:本文系公眾號 "Java技術棧" 原創,原創實屬不易,轉載、引用本文內容請註明出處,禁止抄襲、洗稿,請自重,尊重他人勞動成果和智慧財產權。

相關文章