理解Java putIfAbsent函數

引言

Java中的Map類是一種常用的數據結構,常用的實現類包括HashMap、ConcurrentHashMap、LinkedHashMap等。在Map中,putIfAbsent函數是一個比較常用的方法,但是它的作用可能不太清晰。本文將通過多個方面來詳細闡釋Java中putIfAbsent函數的使用方法。

正文

一、putIfAbsent函數的定義

/**
* 如果給定的鍵尚未與某個值相關聯(或映射到null),則將其與給定的值相關聯並返回null,否則返回當前值。
*
* @param key 鍵
* @param value 值
* @return 與key關聯的舊值,如果沒有則返回null。
*/
public V putIfAbsent(K key, V value);

上述代碼摘自Java8的HashMap類,putIfAbsent函數具有一個很明確的作用:如果給定的鍵還沒有值,那麼將此鍵值對插入到Map中,並返回null,如果給定的鍵已經有值,則返回當前存儲的值,不進行插入。

二、putIfAbsent的使用示例

Map map = new HashMap();
Object oldVal = map.putIfAbsent("key", "value");
System.out.println(oldVal); // null
Object newVal = map.putIfAbsent("key", "value2");
System.out.println(newVal); // value

從上述代碼可以看出,首先向Map中插入鍵為「key」,值為「value」的鍵值對,由於之前Map中沒有此鍵,所以putIfAbsent方法返回null。接著又嘗試插入鍵為「key」,值為「value2」的鍵值對,由於Map中已有此鍵,所以putIfAbsent方法返回當前存儲的值「value」。

三、putIfAbsent方法的線程安全性

雖然putIfAbsent方法線程安全,在多線程環境下運行也不會產生死鎖等問題,但是仍有一些需要注意的地方。

首先需要說明的是,putIfAbsent方法的線程安全性是針對單個鍵值對而言的。也就是說,不同的線程可以同時操作不同的鍵值對,但是如果操作的是同一個鍵值對,那麼就要考慮線程安全問題了。

Map map = new ConcurrentHashMap();
ExecutorService service = Executors.newFixedThreadPool(3);

service.submit(() -> map.putIfAbsent("key", 1));
service.submit(() -> map.putIfAbsent("key", 2));
service.submit(() -> map.putIfAbsent("key", 3));

從上述代碼可以看出,在創建ConcurrentHashMap實例並提交三個線程執行putIfAbsent方法操作同一個鍵值對時,線程間可能產生競爭,會出現多個線程操作同一個鍵值對的情況。在這種情況下,我們需要通過加鎖或使用ConcurrentHashMap等線程安全的Map實現來解決。

四、putIfAbsent方法在代碼中的實際應用場景

實際應用場景中,putIfAbsent方法也有很多場景。

1. 緩存數據

private Map cache = new ConcurrentHashMap();

public Object getData(String key) {
    // 先從緩存中獲取數據
    Object data = cache.get(key);
    if (data == null) {
        // 如果緩存中沒有數據,則從資料庫中讀取,並添加到緩存
        data = fetchDataFromDB(key); // 假設這個方法從資料庫中獲取數據
        cache.putIfAbsent(key, data);
    }
    return data;
}

緩存數據是putIfAbsent方法常用的場景之一,上述代碼邏輯是先從緩存中獲取數據,如果緩存中沒有數據則從資料庫中獲取,然後將獲取到的數據添加到緩存中

2. 分散式鎖

public boolean acquireLock(String lockKey, String owner) {
    // 其他線程已經獲取到鎖
    if (cache.containsKey(lockKey)) {
        return false;
    } else {
        // 嘗試獲取分散式鎖
        if (cache.putIfAbsent(lockKey, owner) == null) {
            return true;
        } else {
            return false;
        }
    }
}

public void releaseLock(String lockKey, String owner) {
    // 釋放分散式鎖
    cache.remove(lockKey, owner);
}

分散式鎖也是putIfAbsent方法的一個常見應用場景。上述代碼通過向緩存添加鍵值對形式的鎖實現分散式鎖,如果lockKey已經存在,則說明其他線程已經獲得了鎖,無法獲取,否則可以獲得鎖。

總結

本文詳細闡述了Java中putIfAbsent方法的定義、使用示例、線程安全性、實際應用場景等方面。putIfAbsent方法是Map類的重要方法之一,在實際編程過程中如果掌握了這個方法的使用方法,可以讓代碼更加簡潔、高效。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/230544.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-10 18:17
下一篇 2024-12-10 18:17

相關推薦

  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Python中capitalize函數的使用

    在Python的字元串操作中,capitalize函數常常被用到,這個函數可以使字元串中的第一個單詞首字母大寫,其餘字母小寫。在本文中,我們將從以下幾個方面對capitalize函…

    編程 2025-04-29
  • Java Bean載入過程

    Java Bean載入過程涉及到類載入器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean載入的過程。 一、類載入器 類載入器是Java虛擬機…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Python中set函數的作用

    Python中set函數是一個有用的數據類型,可以被用於許多編程場景中。在這篇文章中,我們將學習Python中set函數的多個方面,從而深入了解這個函數在Python中的用途。 一…

    編程 2025-04-29
  • 三角函數用英語怎麼說

    三角函數,即三角比函數,是指在一個銳角三角形中某一角的對邊、鄰邊之比。在數學中,三角函數包括正弦、餘弦、正切等,它們在數學、物理、工程和計算機等領域都得到了廣泛的應用。 一、正弦函…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29

發表回復

登錄後才能評論