您的位置:

Java computeIfAbsent 方法详解

一、Java 的 ConcurrentHashMap

在讨论 computeIfAbsent 方法之前,我们需要先了解一下 Java 中的 ConcurrentHashMap。ConcurrentHashMap 是一个线程安全的哈希表,实现了 Map 接口。它被设计用来支持高并发,因为它可以在多个线程同时访问一个或多个桶(buckets)而不会出现数据不一致的情况。

ConcurrentHashMap 的实现方式与 HashMap 不同。它将哈希表分为许多桶,并且每个桶都是一个单独的锁。当一个线程访问哈希表的某个桶时,只有这个桶被锁定,其他线程可以同时访问其他桶。这使得 ConcurrentHashMap 可以支持高并发。

ConcurrentHashMap map = new ConcurrentHashMap<>();

  

二、computeIfAbsent 方法的定义和作用

1、什么是 computeIfAbsent 方法

computeIfAbsent 方法是 ConcurrentHashMap 中的一个方法。它的作用是:如果指定的 key 在 map 中不存在,那么就使用指定的函数计算它的值,并将 key-value 对添加到 map 中。如果指定的 key 已经存在于 map 中,则返回其对应的 value 值。

2、computeIfAbsent 方法的定义

computeIfAbsent 方法的定义如下:

default V computeIfAbsent(K key, Function mappingFunction)

其中,参数 key 表示要操作的 key,参数 mappingFunction 表示计算 key 对应的 value 的函数,它的类型为 Function。

3、computeIfAbsent 方法的作用

当调用 computeIfAbsent 方法时,ConcurrentHashMap 会检查指定的 key 是否已经存在于哈希表中。如果 key 已经存在,则将与之关联的 value 返回。如果 key 不存在,则传递给 computeIfAbsent 方法的 mappingFunction 函数将被调用。该函数将 key 作为参数,返回一个新的 value。新的 key-value 对将自动添加到 ConcurrentHashMap 中,并且 computeIfAbsent 会返回新的 value。

三、computeIfAbsent 方法的使用

下面我们来看一个 computeIfAbsent 方法的使用示例。代码中使用了 ConcurrentHashMap,里面存放了若干个 Fruit 对象,每个 Fruit 对象包含了水果的名称和价格。

import java.util.concurrent.ConcurrentHashMap;

class Fruit {
    private String name;
    private int price;

    public Fruit(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public int getPrice() {
        return price;
    }
}

public class ConcurrentHashMapDemo {

    public static void main(String[] args) {
        ConcurrentHashMap map = new ConcurrentHashMap<>();

        // 果盘里没有苹果,就添加一个苹果对象
        Fruit apple = map.computeIfAbsent("apple", key -> new Fruit("apple", 2));
        System.out.println(apple.getName() + ": " + apple.getPrice());

        // 果盘里已经有苹果了,就不需要再新建一个苹果对象了
        Fruit anotherApple = map.computeIfAbsent("apple", key -> new Fruit("another apple", 3));
        System.out.println(anotherApple.getName() + ": " + anotherApple.getPrice());
    }
}

  

运行上述代码,输出结果如下:

apple: 2
apple: 2

我们可以看到,第一次调用 computeIfAbsent 方法时,果盘里没有苹果,因此新建了一个名为 "apple" 的苹果对象,并将其添加到 map 中。第二次调用 computeIfAbsent 方法时,果盘里已经有了一个名为 "apple" 的苹果对象,因此第二个参数中的 lambda 表达式不会被执行,而是直接返回 map 中已有的苹果对象。

四、computeIfAbsent 方法的优点

使用 computeIfAbsent 方法可以省略掉一些 if 判断和 synchronized 同步,因为 computeIfAbsent 已经保证了线程安全。此外,在使用 computeIfAbsent 方法时,我们可以像示例代码中一样使用 lambda 表达式,使代码更加简洁易读。

五、小结

在 Java 中,ConcurrentHashMap 是一个支持高并发的线程安全 Map。它提供了许多常用的方法,其中包括 computeIfAbsent 方法。使用 computeIfAbsent 方法可以有效地处理多线程并发的问题,同时也能使代码更加简洁易读。在实际开发中,我们应该充分发挥 ConcurrentHashMap 的优势,使用 computeIfAbsent 方法来实现线程安全的数据处理。