map.merge(num, 1, Integer::sum); 和 map.put(num, map.getOrDefault(num, 0) + 1);的对比
以下是对 map.merge(num, 1, Integer::sum); 和 map.put(num, map.getOrDefault(num, 0) + 1); 的比较:
代码示例
以下是使用 map.merge(num, 1, Integer::sum); 的示例代码:
for (int num : nums) {
map.merge(num,1,Integer::sum);
}

以下是使用 map.put(num, map.getOrDefault(num, 0) + 1); 的示例代码:
for (int num : nums) {
map.put(num,map.getOrDefault(num,0)+1);
}

功能解释
-
map.merge(num, 1, Integer::sum);:
- 当
num键不存在时,直接将键值对(num, 1)插入到map中。 - 当
num键已经存在时,使用Integer::sum方法将旧值和新值1相加,更新该键的值。
- 当
-
map.put(num, map.getOrDefault(num, 0) + 1);:
- 首先使用
map.getOrDefault(num, 0)来获取num的值,如果num键不存在,则返回默认值0。 - 然后将获取到的值加
1,并将结果作为num键的新值,使用map.put方法存储到map中。
- 首先使用
区别
-
简洁性:
map.merge(num, 1, Integer::sum);更简洁,使用了merge方法和Integer::sum方法引用,代码更清晰地表达了合并的意图。map.put(num, map.getOrDefault(num, 0) + 1);相对更冗长,需要先调用getOrDefault然后加1再调用put方法。
-
原子性:
map.merge是一个原子操作,在多线程环境下,如果多个线程同时调用merge方法更新同一个键的值,不会出现并发问题。map.put(num, map.getOrDefault(num, 0) + 1);不是原子操作,在多线程环境下,可能会出现并发问题。例如,线程 A 调用map.getOrDefault(num, 0)得到旧值,在计算map.getOrDefault(num, 0) + 1的过程中,线程 B 可能修改了num的值,导致结果不一致。
性能考虑
-
map.merge(num, 1, Integer::sum);:
- 当键不存在时,性能开销稍大,因为需要调用
merge方法并执行合并函数(尽管合并函数很简单)。 - 当键存在时,性能取决于合并函数的复杂程度,对于
Integer::sum这种简单函数,性能较好。
- 当键不存在时,性能开销稍大,因为需要调用
-
map.put(num, map.getOrDefault(num, 0) + 1);:
- 对于键不存在的情况,需要调用
getOrDefault方法,性能稍逊于merge方法的直接添加操作。 - 对于键存在的情况,性能与
merge方法相当,但由于代码更分散,可能导致可读性稍差。
- 对于键不存在的情况,需要调用
适用场景
-
map.merge(num, 1, Integer::sum);:
- 适用于需要合并操作且对代码简洁性和原子性有要求的场景,尤其是在并发环境中。
- 适用于更复杂的合并操作,如合并两个集合、列表或自定义的合并逻辑,只需要修改合并函数即可。
-
map.put(num, map.getOrDefault(num, 0) + 1);:
- 适用于简单的更新计数或递增操作,当不考虑并发问题时,使用
put方法也比较方便。
- 适用于简单的更新计数或递增操作,当不考虑并发问题时,使用
总的来说,map.merge(num, 1, Integer::sum); 更适合处理合并和更新操作,特别是在多线程环境下,而 map.put(num, map.getOrDefault(num, 0) + 1); 更适合简单的递增计数操作,在单线程环境中使用。

浙公网安备 33010602011771号