Java 8 Map合并VS计算,本质区别?

J.J*_*eam 11 collections java-8

似乎合并和计算 Map 方法都被创建来减少 if("~key exists here~") 放置时。我的问题是:当我什么都不知道时添加到映射 [key, value] 对:map 中既不存在键也不存在但具有 value 或 value == null 或 key == null。

words.forEach(word ->
        map.compute(word, (w, prev) -> prev != null ? prev + 1 : 1)
);
words.forEach(word ->
        map.merge(word, 1, (prev, one) -> prev + one)
);
Run Code Online (Sandbox Code Playgroud)

唯一的区别是 1 从 Bifunction 移到了参数吗?什么更好用?是否有任何合并、计算表明 key/val 存在?它们的用例有什么本质区别?

Sla*_*law 11

的文档Map#compute(K, BiFunction)说:

尝试计算指定键及其当前映射值的映射(或者null如果没有当前映射)。例如,要创建或附加String msg一个值映射:

map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))
Run Code Online (Sandbox Code Playgroud)

merge()用于此类目的的方法通常更简单。)

如果重映射函数返回null,则删除映射(如果最初不存在,则保持不存在)。如果重映射函数本身抛出(未经检查的)异常,则重新抛出异常,并且当前映射保持不变。

重新映射函数不应在计算期间修改此映射。

和文档Map#merge(K, V, BiFunction)说:

如果指定的键尚未与值关联或与 null 关联,则将其与给定的非 null 值关联。否则,用给定重映射函数的结果替换关联的值,如果结果为 ,则删除null。当为一个键组合多个映射值时,此方法可能有用。例如,要创建或附加String msg一个值映射:

map.merge(key, msg, String::concat)
Run Code Online (Sandbox Code Playgroud)

如果重映射函数返回null,则删除映射。如果重映射函数本身抛出(未经检查的)异常,则重新抛出异常,并且当前映射保持不变。

重新映射函数不应在计算期间修改此映射。

重要的区别是:

  • 对于compute(K, BiFunction<? super K, ? super V, ? extends V>)

    • BiFunction始终调用。
    • BiFunction接受给定的密钥和当前值,如果有的话,作为参数,并返回一个新值。
    • 用于获取键和当前值(如果有),执行任意计算并返回结果。计算可能是一个归约操作(即合并),但它不一定是。
  • 对于merge(K, V, BiFunction<? super V, ? super V, ? extends V>)

    • BiFunction调用仅在给定密钥已与非空值相关联
    • BiFunction接受当前值与给定值作为参数,并返回一个新值。与 不同computeBiFunction没有给出密钥。
    • 用于取两个值并将它们化简为一个值。

  • 所以看起来合并是计算的一个特殊情况,不是吗? (2认同)
  • 在大多数情况下,看起来确实如此。但有一个主要区别,“compute”将键和当前值传递给“BiFunction”,而“merge”将当前值和给定(即新)值传递给“BiFunction”。这改变了“BiFunction”实现的使用方式。换句话说,对于“compute”来说,键看起来也应该是,或者至少可以是计算的一部分,但对于“merge”来说,键看起来应该是无关紧要的。 (2认同)