Map.computeIfAbsent 中奇怪的 lambda 行为

问题描述 投票:0回答:1

我创建了以下方法,将给定的 UUID 值与给定的 Integer 添加到

map
变量。

final Map<Integer, List<UUID>> map = new TreeMap<>();

private void addToMap(Integer key, UUID value) {
    map.computeIfAbsent(key, val -> new ArrayList<>()).add(value);
}

通常,我尝试通过将

map.computeIfAbsent(key, value -> new ArrayList<>()).add(value);
参数传递给 lambda 函数来使用
value
,它会抛出“变量‘值’已在范围中定义”错误,指向
.. value ->  ...
部分中的“值”。

我更新的

addToMap
方法有效,但我认为
val
毫无意义。那么,这个方法应该如何更新呢?

java dictionary lambda
1个回答
3
投票

你的

addToMap()
方法暗示着对
computeIfAbsent()
方法参数的错误理解:

private void addToMap(Integer key, UUID value) {
    map.computeIfAbsent(key, val -> new ArrayList<>()).add(value);
}

val -> new ArrayList<>()
中的参数与你传入
value
addToMap()
无关!

如果您查看 Map.computeIfAbsent() 的 JavaDoc,您可以看到第二个参数是

Function<? super K,​? extends V>
- 即一个函数,它接受一个键并返回应存储在地图中的任何内容。

最好将

addToMap()
方法写为

private void addToMap(Integer key, UUID value) {
    map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
}

请注意,toniedzwiedz 的答案是危险的。它仅适用于键大于或等于零的

Map<Integer, ?>

这很危险,因为它基本上用

k -> new ArrayList<>()
代替了
k -> new ArrayList<>(k)
- 这恰好适用于带有
Integer
键的地图,并使用键值来定义
ArrayList
的初始容量。

如果

k
为负数,则不起作用(如果 k 为负数,
new ArrayList<>(k)
将抛出
IllegalArgumentException
)。

它也不适用于

Map<String, UUID>
,因为没有带有
ArrayList
参数的
String
构造函数。

© www.soinside.com 2019 - 2024. All rights reserved.