"Variable expected" 在具有可为空类型的可变映射上调用 getValue 时出错
"Variable expected" error when calling getValue on a mutable map with a nullable type
我在更改可变映射的值时遇到问题。我认为这与可空类型有关,但我不确定。产生错误的代码如下:
fun countHexadecimalNumbers(codes: List<String>): Map<Int, Int> {
val map = mutableMapOf<Int, Int>()
for (s in codes) {
val num = s.toIntOrNull(16)
if (num != null) {
if (num !in map.keys) {
map[num] = 0
}
map.getValue(num) += 1 %<--This line causes the issue
}
}
return map
当我尝试构建代码时出现此错误:
Nullable Types\Exercise 3\src\Task.kt: (13, 11): Variable expected
有人知道为什么不允许这样做吗?
语句map.getValue(num) += 1
是不允许的,因为+=
运算符只在两种情况下定义:
- a plusAssign() 运算符是在左操作数的类型上定义的(
Int
不是这种情况)
- a plus() 运算符定义在左操作数的类型上,并且左操作数是一个 变量 。在这种情况下
+=
将左侧的变量重新分配为 oldValue.plus(the right operand)
.
编译器在这里尝试考虑案例 #2,因为 Int.plus(Int)
已定义,但左操作数不是变量,因此它失败并显示您提到的错误消息。
你不能写这个的原因和你不能写 map.getValue(num) = 42
.
的原因一样
改变映射中值的正确方法是通过 set operator (like you did earlier with the syntax sugar map[num] = 0
), or via other mutating functions like merge.
在您的情况下,merge
很好,因为它可以完全删除特殊情况(尽管它仅在 JVM 目标上可用):
val map = mutableMapOf<Int, Int>()
for (s in codes) {
val num = s.toIntOrNull(16)
if (num != null) {
map.merge(num, 1, Int::plus)
}
}
这是 merge
的作用:
- 如果键不存在于映射中,它只是将给定的值设置为第二个参数(值 1)
- 如果键已经存在,则使用作为第三个参数给出的函数(只是一个总和)计算一个新值。该函数以旧值和第二个参数(值 1)作为输入调用,并且应该 return 分配新值,所以在这种情况下
old + 1
.
请注意,在您的情况下,整个循环可以这样简化:
fun countHexadecimalNumbers(codes: List<String>): Map<Int, Int> {
return codes.mapNotNull { it.toIntOrNull(16) }.groupingBy { it }.eachCount()
}
我在更改可变映射的值时遇到问题。我认为这与可空类型有关,但我不确定。产生错误的代码如下:
fun countHexadecimalNumbers(codes: List<String>): Map<Int, Int> {
val map = mutableMapOf<Int, Int>()
for (s in codes) {
val num = s.toIntOrNull(16)
if (num != null) {
if (num !in map.keys) {
map[num] = 0
}
map.getValue(num) += 1 %<--This line causes the issue
}
}
return map
当我尝试构建代码时出现此错误:
Nullable Types\Exercise 3\src\Task.kt: (13, 11): Variable expected
有人知道为什么不允许这样做吗?
语句map.getValue(num) += 1
是不允许的,因为+=
运算符只在两种情况下定义:
- a plusAssign() 运算符是在左操作数的类型上定义的(
Int
不是这种情况) - a plus() 运算符定义在左操作数的类型上,并且左操作数是一个 变量 。在这种情况下
+=
将左侧的变量重新分配为oldValue.plus(the right operand)
.
编译器在这里尝试考虑案例 #2,因为 Int.plus(Int)
已定义,但左操作数不是变量,因此它失败并显示您提到的错误消息。
你不能写这个的原因和你不能写 map.getValue(num) = 42
.
改变映射中值的正确方法是通过 set operator (like you did earlier with the syntax sugar map[num] = 0
), or via other mutating functions like merge.
在您的情况下,merge
很好,因为它可以完全删除特殊情况(尽管它仅在 JVM 目标上可用):
val map = mutableMapOf<Int, Int>()
for (s in codes) {
val num = s.toIntOrNull(16)
if (num != null) {
map.merge(num, 1, Int::plus)
}
}
这是 merge
的作用:
- 如果键不存在于映射中,它只是将给定的值设置为第二个参数(值 1)
- 如果键已经存在,则使用作为第三个参数给出的函数(只是一个总和)计算一个新值。该函数以旧值和第二个参数(值 1)作为输入调用,并且应该 return 分配新值,所以在这种情况下
old + 1
.
请注意,在您的情况下,整个循环可以这样简化:
fun countHexadecimalNumbers(codes: List<String>): Map<Int, Int> {
return codes.mapNotNull { it.toIntOrNull(16) }.groupingBy { it }.eachCount()
}