computeIfAbsent()介绍及代码示例

在 Java 中,nodeMap.computeIfAbsent() 是 java.util.Map 接口(及其实现类,如 HashMap)提供的一个方法,用于 根据键获取值,若键不存在则计算并插入新值。它属于 Java 8 引入的函数式编程增强特性,常用于简化条件判断和值的初始化逻辑。

方法签名

V computeIfAbsent(K key, Function mappingFunction)

  • 参数
    • key:要查询的键。
    • mappingFunction:一个函数,用于在键不存在时计算新值(输入为键,输出为对应的值)。
  • 返回值
    • 若键存在,返回已有的值;
    • 若键不存在,调用 mappingFunction 计算新值并插入到 Map 中,然后返回该新值。

核心逻辑与示例

场景 1:键存在时直接返回值
Map countMap = new HashMap<>();
countMap.put("apple", 5); // 键 "apple" 已存在

// 调用 computeIfAbsent,键存在,直接返回已有值 5
Integer count = countMap.computeIfAbsent("apple", k -> k.length()); 
System.out.println(count); // 输出:5(mappingFunction 不会被调用)
场景 2:键不存在时计算并插入新值
Map countMap = new HashMap<>();
// 键 "banana" 不存在,调用 mappingFunction 计算新值("banana".length() = 6)
Integer count = countMap.computeIfAbsent("banana", k -> k.length()); 
System.out.println(count); // 输出:6
System.out.println(countMap.get("banana")); // 输出:6(值已插入 Map)

常见用途

1. 简化计数逻辑(替代 putIfAbsent

传统计数需要先判断键是否存在,再手动赋值:

// 传统方式
if (!countMap.containsKey("apple")) {
    countMap.put("apple", 1);
} else {
    countMap.put("apple", countMap.get("apple") + 1);
}

// 用 computeIfAbsent 简化(配合 merge 更高效)
countMap.merge("apple", 1, Integer::sum); // 更推荐的计数方式
2. 初始化复杂值(如嵌套集合)
Map> groupMap = new HashMap<>();
// 当键 "group1" 不存在时,创建新列表并插入
groupMap.computeIfAbsent("group1", k -> new ArrayList<>()).add("item1");
// 此时 groupMap 中 "group1" 对应的值为 [item1]
3. 惰性初始化(延迟加载)

仅在需要时创建值,避免提前初始化开销:

class DataLoader {
    private final Map dataCache = new HashMap<>();

    public Data loadData(String key) {
        // 若 key 对应的 Data 不存在,才调用 loadFromDatabase 加载
        return dataCache.computeIfAbsent(key, this::loadFromDatabase);
    }

    private Data loadFromDatabase(String key) {
        // 模拟从数据库加载数据
        return new Data(key);
    }
}

注意事项

  1. 线程安全

    • 该方法本身并非线程安全,若在多线程环境下使用,需配合 ConcurrentHashMap 或手动加锁。
    • ConcurrentHashMap 提供了同名方法 computeIfAbsent,内部实现了线程安全。
  2. 函数式接口的要求

    • mappingFunction 不能为 null,否则会抛出 NullPointerException
    • 若 mappingFunction 返回 null,会导致键被移除(仅适用于允许 null 值的 Map,如 HashMap)。
  3. 性能考量

    • 若键存在,直接返回值,时间复杂度为 O(1)(取决于底层 Map 的实现);
    • 若键不存在,需计算新值并插入,时间复杂度为 O(1)(平均情况,HashMap 为例)。

与其他方法的对比

方法 功能描述
putIfAbsent(key, value) 若键不存在则插入固定值,存在则不修改。
compute(key, function) 无论键是否存在,都用 function 重新计算值(存在时传入旧值,不存在时传入 null)。
computeIfAbsent(key, function) 仅在键不存在时用 function 计算值并插入,存在时返回旧值。

总结computeIfAbsent 是处理 “懒加载” 和 “条件初始化” 场景的高效工具,能减少样板代码,使逻辑更简洁。

你可能感兴趣的:(java,数据库,开发语言)