以下是对 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);
更适合简单的递增计数操作,在单线程环境中使用。