为什么 v != null ?v++ : 1 与 (v != null ? v : 0) + 1 在 HashMap.compute 上递增键不同?

Gab*_*ado 3 java hashmap java-8

我想应用一个计算方法,如果键存在则增加值,否则放 1。

Map<Integer, Integer> map = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

我不明白为什么

for (int i = 0; i < 10; i++) map.compute(1, (k, v) -> v != null ? v++ : 1);
Run Code Online (Sandbox Code Playgroud)

结果{1=1}

for (int i = 0; i < 10; i++) map.compute(1, (k, v) -> (v != null ? v : 0) + 1);
Run Code Online (Sandbox Code Playgroud)

结果{1=10}?

我对第一种情况的理解是:

  • 如果有一个带有 key 的值k,则从中获取结果v++并将其放回原处,否则用 1 填充

而秒的情况是:

  • 如果有一个带有 k ksave的值v+1,否则 save 0+1,它也是 1

为什么在这种情况下运行v++不会导致v+1

ern*_*t_k 5

因为(k, v) -> (v != null) ? v++ : 1在第一次迭代后总是返回 1。

在第一次迭代中,v != null将评估为 false 并将1映射到 key 1。在所有后续调用中,条件将为真并且v++将被使用,事实上v++正在使用的后增量1将始终是新的映射值(而不是 2)。

v++递增 lambda 表达式的局部参数,而不是映射中的值(请记住,Java 是按值传递的

如果您使用++v而不是v++,您也会得到 10。这将起作用,因为新的映射值已经递增(不同于v++取值然后递增v

(v != null ? v : 0) + 1,另一方面,将始终添加1到当前映射的值(它不会受到 的行为的影响v++

  • 嗯,更简单的是 `map.merge(key, 1, (a, b) -&gt; a + b);` 或 `map.merge(key, 1, Integer::sum);` (3认同)