在具有可为空类型的可变映射上调用 getValue 时出现"Variable expected"错误



我在更改可变映射的值时遇到问题。我认为这与可为null的类型有关,但我不确定。产生错误的代码如下:

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 TypesExercise 3srcTask.kt: (13, 11): Variable expected

有人知道为什么不允许这样做吗?

不允许使用语句map.getValue(num) += 1,因为+=运算符只在两种情况下定义:

  1. plusAssign((运算符是在左操作数的类型上定义的(而不是Int的情况(
  2. 在左操作数的类型AND上定义了一个加号((运算符,左操作数是变量。在这种情况下,+=oldValue.plus(the right operand)重新分配左边的变量

编译器尝试在这里考虑情况#2,因为定义了Int.plus(Int),但左操作数不是变量,因此它失败,并显示您提到的错误消息。你不能写这篇文章的原因和你不能写map.getValue(num) = 42的原因一样。

更改映射中值的正确方法是通过set运算符(就像您之前使用语法糖map[num] = 0所做的那样(,或者通过其他更改函数(如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(作为输入进行调用,并且应该返回要分配的新值,因此在本例中为old + 1

注意,在您的情况下,整个循环可以通过以下方式简化:

fun countHexadecimalNumbers(codes: List<String>): Map<Int, Int> {
return codes.mapNotNull { it.toIntOrNull(16) }.groupingBy { it }.eachCount()
}

最新更新