4

给定一个 Map 或 MutableMap:

val scores: MutableMap<String, Int> = mutableMapOf(
        "some person" to 0,
        "some other person" to 0,
        "you" to 0,
        "me" to 0
)

我无法像在 Python 中那样增加这些,而且我不确定这样做的正确方法是什么,或者是否可能。

fun test() {
    scores["you"] += 2
}

这给出了错误:

Operator call corresponds to a dot-qualified call 'scores["you"].plusAssign(2)' which is not allowed on a nullable receiver 'scores["you"]'.

我不确定这里发生了什么。

4

2 回答 2

1

+=运算符是plusAssign函数 ( doc )的简写运算符,用于向可变映射或集合添加或替换条目,如 Kotlin doc为映射操作指定的那样

您还可以使用速记运算符表单向地图添加新条目。有两种方法:

  • plusAssign(+=) 运算符。
  • []运算符别名set()

当您使用scores["you"] += 2, since+=是 的简写运算符时plusAssign,并且scores["you"]可以返回一个可为空的值(地图上的任何get操作都可以),您会收到编译错误

Operator call corresponds to a dot-qualified call 'scores["you"].plusAssign(2)' which is not allowed on a nullable receiver 'scores["you"]'.

对于您的用例,您可以更好地使用地图上的merge方法(doc),如下所示

scores.merge("you", 2, Int::plus)

请注意,merge即使地图中不存在密钥,也会向地图添加一个条目。如果您只想在键存在于地图中时才增加键的值,您可以使用如下computeIfPresent方法(doc

scores.computeIfPresent("you"){ _, v -> v + 2 }
于 2020-11-17T02:41:25.267 回答
0

最佳答案包含虚假信息。它并不总是寻找运算符,在某些情况下plusAssign可以使用索引。+=

根据实际文档,它首先查找,如果没有可用的运算符函数plusAssign,则使用它plus,如果没有plusAssign可用的,它会尝试生成类似的代码:a = a + b

如果您要使用ArrayList,它可以工作,例如:

val arr = arrayListOf(1, 2, 3, 4)
arr[0] += 4  // arr[0] = arr[0] + 4 -> arr.set(0, arr.get(0) + 4)
arr // 5, 2, 3, 4

唯一的问题是当键未映射到映射中的值时map[key]返回引用。null所以这是另一种方法,没有点限定调用:

val map = hashMapOf(1 to 2, 3 to 4)
// map += 1 to map[1]!! + 2 // If you are sure about the key 
map += 1 to ((map[1] ?: 0) + 2) // map.put(1, (map.get(1) ?: 0) + 2)
map // { 1: 4, 3: 4 }

你甚至不需要使用该merge方法,只需添加一个扩展函数:

operator fun Int?.plus(other: Int) = this?.plus(other) ?: other
fun main() {
    val map = hashMapOf(1 to 2, 3 to 4)
    map[1] += 2 // map[1] = map[1] + 2 -> map.put(1, map.get(1).plus(2))
}
于 2020-11-18T05:35:44.480 回答