Java Map 常用方法大全
1. 基础操作
方法 | 描述 | 示例 |
---|---|---|
put(K key, V value) | 添加键值对(覆盖旧值) | map.put("a", 1) |
get(Object key) | 获取指定键的值 | map.get("a") → 1 |
containsKey(Object key) | 检查是否包含键 | map.containsKey("a") → true |
containsValue(Object value) | 检查是否包含值 | map.containsValue(1) → true |
remove(Object key) | 删除指定键的映射 | map.remove("a") → 1 |
size() | 返回键值对数量 | map.size() → 1 |
isEmpty() | 检查是否为空 | map.isEmpty() → false |
clear() | 清空所有映射 | map.clear() |
2. 批量操作
方法 | 描述 | 示例 |
---|---|---|
putAll(Map<? extends K, ? extends V> m) | 合并另一个Map的所有映射 | map1.putAll(map2) |
replaceAll(BiFunction<? super K, ? super V, ? extends V> function) | 替换所有值 | map.replaceAll((k, v) -> v + 1) |
3. 高级操作(Java 8+)
方法 | 描述 | 示例 |
---|---|---|
computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) | 键不存在时计算新值 | map.computeIfAbsent("a", k -> new ArrayList<>()) |
computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) | 键存在时重新计算值 | map.computeIfPresent("a", (k, v) -> v + 1) |
compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) | 强制计算新值(无论键是否存在) | map.compute("a", (k, v) -> v == null ? 1 : v + 1) |
merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) | 合并值(处理冲突) | map.merge("a", 1, (old, new) -> old + new) |
getOrDefault(Object key, V defaultValue) | 安全获取值(不存在时返回默认值) | map.getOrDefault("b", 0) → 0 |
putIfAbsent(K key, V value) | 键不存在时插入值 | map.putIfAbsent("a", 1) |
4. 遍历与视图
方法 | 描述 | 示例 |
---|---|---|
forEach(BiConsumer<? super K, ? super V> action) | 遍历所有键值对 | map.forEach((k, v) -> System.out.println(k + ":" + v)) |
keySet() | 返回所有键的Set视图 | map.keySet() → ["a"] |
values() | 返回所有值的Collection视图 | map.values() → [1] |
entrySet() | 返回所有键值对的Set视图 | map.entrySet() → [{"a":1}] |
5. 并发安全操作(ConcurrentHashMap特有)
方法 | 描述 | 示例 |
---|---|---|
forEach(long parallelismThreshold, BiConsumer<? super K,? super V> action) | 并行遍历 | map.forEach(2, (k, v) -> process(k, v)) |
reduce(long parallelismThreshold, BiFunction<? super K,? super V,? extends U> transformer, BiFunction<? super U,? super U,? extends U> reducer) | 并行归约 | map.reduce(2, (k, v) -> v, (a, b) -> a + b) |
6. 不可变Map(Java 9+)
方法 | 描述 | 示例 |
---|---|---|
Map.of(k1, v1, k2, v2...) | 创建不可变Map(最多10个键值对) | Map.of("a", 1, "b", 2) |
Map.ofEntries(Map.Entry<? extends K,? extends V>... entries) | 通过Entry创建不可变Map | Map.ofEntries(entry("a", 1), entry("b", 2)) |
Map.copyOf(Map<? extends K,? extends V> map) | 复制为不可变Map | Map.copyOf(existingMap) |
使用场景总结
快速查询:
get()
/getOrDefault()
条件插入:
putIfAbsent()
/computeIfAbsent()
原子更新:
compute()
/merge()
批量处理:
forEach()
/replaceAll()
并发安全:
ConcurrentHashMap
的并行方法防御性编程:
Map.copyOf()
创建不可变Map
Java Map 关键方法对比表
方法名 | 描述 | 是否修改Map | 返回值 | 典型应用场景 | 示例 |
---|---|---|---|---|---|
getOrDefault | 安全获取值,键不存在时返回默认值 | ❌ 只读 | 值或默认值 | 避免Null检查的查询 | map.getOrDefault("a", 0) → 不存在时返回0 |
computeIfAbsent | 键不存在时,通过函数计算新值并插入;键存在时直接返回旧值 | ✅ 条件写入 | 旧值或新计算的值 | 懒加载(如初始化列表) | map.computeIfAbsent("a", k -> new ArrayList<>()) |
putIfAbsent | 键不存在时插入给定值;键存在时不做操作 | ✅ 条件写入 | 旧值或null | 原子性初始化(简单值) | map.putIfAbsent("a", 1) → 不存在时插入1 |
computeIfPresent | 键存在时,通过函数重新计算值;键不存在时不做操作 | ✅ 条件写入 | 新值或null | 条件更新(如计数器重置) | map.computeIfPresent("a", (k, v) -> v + 1) → 存在时值+1 |
compute | 无论键是否存在,都通过函数计算新值(可删除键) | ✅ 强制写入 | 新值或null(若删除) | 复杂更新逻辑 | map.compute("a", (k, v) -> v == null ? 1 : v + 1) |
merge | 合并新旧值(键不存在时插入给定值;存在时通过函数合并) | ✅ 条件写入 | 合并后的值 | 累加或去重 | map.merge("a", 1, (old, new) -> old + new) → 值累加 |
tips:
computeIfPresent
中的 k
参数详解
在 map.computeIfPresent("a", (k, v) -> v + 1)
中:
k
是当前处理的键(这里是"a"
),属于BiFunction
的必需参数。v
是该键对应的当前值。
核心区别总结
是否修改Map
只读:
getOrDefault
条件修改:
computeIfAbsent
、putIfAbsent
、computeIfPresent
、merge
强制修改:
compute
默认值/新值来源
固定值:
putIfAbsent
、getOrDefault
函数生成:
computeIfAbsent
、computeIfPresent
、compute
合并函数:
merge
典型场景
避免Null检查 →
getOrDefault
懒加载初始化 →
computeIfAbsent
原子性插入 →
putIfAbsent
条件更新 →
computeIfPresent
复杂合并逻辑 →
merge
经典示例对比
1. 统计字符频率
// 方法1: getOrDefault + put(强制更新)
map.put(c, map.getOrDefault(c, 0) + 1);// 方法2: merge(更简洁)
map.merge(c, 1, (old, newVal) -> old + newVal);// 方法3: compute(完全控制)
map.compute(c, (k, v) -> v == null ? 1 : v + 1);
2. 初始化邻接表
// 方法1: computeIfAbsent(最优)
graph.computeIfAbsent(node, k -> new ArrayList<>()).add(neighbor);// 方法2: putIfAbsent + get(冗长)
if (!graph.containsKey(node)) {graph.put(node, new ArrayList<>());
}
graph.get(node).add(neighbor);
如何选择?
需求 | 推荐方法 | 原因 |
---|---|---|
安全读取(带默认值) | getOrDefault | 代码简洁,不修改Map |
初始化复杂对象 | computeIfAbsent | 避免重复创建对象,线程安全(配合ConcurrentHashMap) |
简单值原子插入 | putIfAbsent | 语义明确,性能稍优于computeIfAbsent |
条件更新现有值 | computeIfPresent | 精准控制已有键的更新逻辑 |
复杂合并逻辑(如累加) | merge | 内置合并函数,代码最简洁 |