JAVA8的computeIfAbsent使用方法

基础说明

computeIfAbsent 是 Java 8 引入的 Map 接口中的一个默认方法。它允许你以原子操作的方式在给定键不存在时计算其值,并将其添加到映射中。如果该键已经存在,则返回已存在的值而不执行任何计算。

下面是 computeIfAbsent 的基本用法:

Map<K, V> map = new ConcurrentHashMap<>();

V value = map.computeIfAbsent(key, k -> {
    // 只有当 key 对应的 value 不存在时,这段代码才会执行。
    // 计算新的 value 值,通常这里会是一个可能较耗时的操作。
    return computeExpensiveValue(k);
});

在这个例子中,computeExpensiveValue(k) 方法只会在 key 不在 map 中的时候调用。如果 key 已经存在,那么它将直接返回对应的值而不会执行提供的映射函数。

用法理解

computeIfAbsent 方法特别适用于缓存场景,尤其是在需要避免重复执行资源密集型操作的情况下。当一个键不在映射中时,使用 computeIfAbsent 可以确保只计算一次值,并将其存储在映射中供后续使用,从而提高性能和效率。

为了更好地说明这一点,让我们来看一个更详细的例子,其中包含了一个模拟的资源密集型操作,比如从数据库获取数据或进行复杂的计算:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public class ComputeIfAbsentCacheExample {

    // 模拟的缓存
    private static final Map<Integer, String> cache = new ConcurrentHashMap<>();

    // 模拟的资源开销大的操作,例如查询数据库
    private static String expensiveDatabaseQuery(Integer id) throws InterruptedException {
        System.out.println("Executing expensive operation for ID: " + id);
        // 模拟延迟
        TimeUnit.SECONDS.sleep(2); // 假设需要2秒来完成这个昂贵的操作
        return "Data for ID: " + id;
    }

    public static void main(String[] args) throws InterruptedException {
        Integer key = 1;

        // 第一次调用 computeIfAbsent,将执行昂贵的操作
        long startTime = System.currentTimeMillis();
        String data = cache.computeIfAbsent(key, ComputeIfAbsentCacheExample::expensiveDatabaseQuery);
        System.out.println("Data: " + data);
        System.out.println("Time taken: " + (System.currentTimeMillis() - startTime) + " ms");

        // 第二次调用,由于值已经在缓存中,所以不会再次执行昂贵的操作
        startTime = System.currentTimeMillis();
        data = cache.computeIfAbsent(key, ComputeIfAbsentCacheExample::expensiveDatabaseQuery);
        System.out.println("Data: " + data);
        System.out.println("Time taken: " + (System.currentTimeMillis() - startTime) + " ms");
        
        // 查看最终的映射内容
        System.out.println("Final map content: " + cache);
    }
}

在这个例子中,第一次调用 computeIfAbsent 会触发 expensiveDatabaseQuery 方法的执行,这可能是一个耗时的操作(如查询数据库)。但是,一旦结果被缓存,后续对该相同键的请求将直接从缓存中返回结果,而不会再次执行昂贵的操作,这样就显著提高了性能。

posted @ 2024-12-06 15:06  地球上的张先生  阅读(42)  评论(0编辑  收藏  举报