在Java集合框架的使用过程中,Map是最常用的数据结构之一,很多场景下我们需要从Map中获取指定键对应的值,但是直接调用get方法时如果键不存在会返回null,因此很多开发者会先通过containsKey方法判断键是否存在,再决定取值逻辑,这种方式会产生大量冗余的条件判断代码。

传统键值存在性判断的冗余写法
我们先看一个常见的业务场景:统计用户访问次数,访问记录存储在Map中,键是用户ID,值是访问次数。传统的实现方式需要先判断用户ID是否已经存在于Map中,如果存在就取出原有次数加1,不存在就初始化为1,代码如下:
import java.util.HashMap;
import java.util.Map;
public class TraditionalMapDemo {
public static void main(String[] args) {
Map<String, Integer> visitCountMap = new HashMap<>();
String userId = "user_001";
// 传统冗余判断逻辑
if (visitCountMap.containsKey(userId)) {
Integer oldCount = visitCountMap.get(userId);
visitCountMap.put(userId, oldCount + 1);
} else {
visitCountMap.put(userId, 1);
}
System.out.println(visitCountMap.get(userId)); // 输出1
}
}
上面的代码虽然能实现功能,但是存在两个问题:首先调用了两次Map的查询操作,先调用containsKey判断存在性,再调用get获取值,效率上有一定损耗;其次代码逻辑比较繁琐,当这类判断逻辑多的时候会让代码变得冗长,可读性下降。
Map.getOrDefault() 方法介绍
getOrDefault是Map接口在Java 8中新增的默认方法,它的作用是获取指定键对应的值,如果键不存在,就返回我们传入的默认值。该方法的源码实现非常简单:
default V getOrDefault(Object key, V defaultValue) {
V v;
// 先尝试获取键对应的值,如果值不为null或者键本身存在于Map中,就返回获取到的值
// 否则返回传入的默认值
return (((v = get(key)) != null) || containsKey(key)) ? v : defaultValue;
}
方法的参数有两个,第一个是要查询的键,第二个是键不存在时返回的默认值。返回值规则是:如果键存在且对应的值不为null,返回该值;如果键存在但对应的值为null,也返回null;如果键不存在,返回传入的默认值。
用 getOrDefault 简化上述场景的代码
我们再用getOrDefault改写之前的访问次数统计逻辑,代码会变得非常简洁:
import java.util.HashMap;
import java.util.Map;
public class GetOrDefaultDemo {
public static void main(String[] args) {
Map<String, Integer> visitCountMap = new HashMap<>();
String userId = "user_001";
// 使用getOrDefault简化逻辑
// 如果用户ID不存在,返回默认值0,然后加1后存入Map
visitCountMap.put(userId, visitCountMap.getOrDefault(userId, 0) + 1);
System.out.println(visitCountMap.get(userId)); // 输出1
}
}
可以看到,原本需要4行逻辑的代码现在只需要1行就完成了,而且只调用了一次Map的查询操作,效率和可读性都得到了提升。
更多适用场景示例
场景1:获取配置项默认值
很多时候我们会从配置Map中读取配置项,如果配置项不存在就使用默认配置,传统写法需要先判断再取值:
import java.util.HashMap;
import java.util.Map;
public class ConfigDemo {
public static void main(String[] args) {
Map<String, String> configMap = new HashMap<>();
configMap.put("max_thread", "10");
// 传统写法
String timeoutConfig;
if (configMap.containsKey("timeout")) {
timeoutConfig = configMap.get("timeout");
} else {
timeoutConfig = "3000";
}
// 使用getOrDefault写法
String timeout = configMap.getOrDefault("timeout", "3000");
String maxThread = configMap.getOrDefault("max_thread", "5");
System.out.println(timeout); // 输出3000
System.out.println(maxThread); // 输出10
}
}
场景2:累加统计场景
比如统计不同商品的销售数量,商品ID作为键,销售数量作为值,每次销售对应商品时累加数量:
import java.util.HashMap;
import java.util.Map;
public class SalesStatDemo {
public static void main(String[] args) {
Map<String, Integer> salesMap = new HashMap<>();
// 模拟两次商品A的销售记录
String productId = "product_A";
salesMap.put(productId, salesMap.getOrDefault(productId, 0) + 1);
salesMap.put(productId, salesMap.getOrDefault(productId, 0) + 1);
System.out.println(salesMap.get(productId)); // 输出2
}
}
使用注意事项
- 默认值类型需要和Map的值类型匹配,比如Map的值是Integer类型,默认值也需要是Integer类型,否则会编译报错。
- 如果Map中允许存储null值,那么当键存在但对应的值为null时,
getOrDefault会返回null而不是默认值,这一点需要注意,避免后续出现空指针异常。 - 该方法不会改变原有Map的结构,只是查询时返回默认值,不会自动把键值对存入Map中,如果需要存入的话需要额外调用put方法,就像前面统计场景中的写法。
通过上面的介绍可以看出,Map.getOrDefault方法可以有效消除冗余的键值存在性判断代码,让代码更简洁易读,在需要获取Map值且需要默认值的场景下非常适用,建议开发者在合适的场景中优先使用该方法简化逻辑。
MapgetOrDefault键值判断Java集合修改时间:2026-07-06 10:30:27