使用哈希映射键的智能投射

Smart Cast with hashmap keys

我正在将一些 Java 应用程序移植到 Kotlin,并且我将 运行 用于哈希映射的这个问题。假设我有两个哈希图:

var firstHashmap: HashMap<String, String> = hashMapOf("foo" to "A", "bar" to "B")
var secondHashmap: HashMap<String, String> = hashMapOf("foo" to "C", "bar" to "D")

如果另一个中存在相同的密钥,我想更新一个:

if (firstHashmap["foo"] != null) {
    secondHashmap["foo"] = firstHashmap["foo"]
}

Kotlin 不会编译第二行,因为 firstHashmap 不能保证有一个“foo”键。我只是在第一行检查它并不重要——智能转换系统显然不适用于散列映射键。这有同样的问题:

if (firstHashmap.containsKey("foo")) {
    secondHashmap["foo"] = firstHashmap["foo"]
}

这可行,但在某些情况下创建额外变量会变得混乱:

val newValue = firstHashmap["foo"]
if (newValue != null) {
    secondHashmap["foo"] = newValue
}

这也有效,但到目前为止我从来没有使用过 !! 修饰符:

if (firstHashmap["foo"] != null) {
    secondHashmap["foo"] = firstHashmap["foo"]!!
}

这行得通,但是永远不会使用 Elvis 运算符之后的默认值,只是为了满足编译器的要求,感觉不对:

if (firstHashmap["foo"] != null) {
    secondHashmap["foo"] = firstHashmap["foo"] ?: ""
}

更进一步,我尝试放弃条件并仅使用 Elvis 运算符,但随后它卡在 secondHashMap 没有保证的密钥:

secondHashmap["foo"] = firstHashmap["foo"] ?: secondHashmap["foo"]

那么这会起作用,但这让我回到添加默认值只是为了欺骗编译器:

secondHashmap["foo"] = firstHashmap["foo"] ?: secondHashmap["foo"] ?: ""

有没有更好的方法来处理这个问题,比如触发智能投射系统知道钥匙真的在那里?否则,我猜 !! 选项似乎是最干净的,尤其是当我从上一行中清楚地看出我选择使用它的原因时。

无法保证 firstHashmap["foo"] returns 每次调用时都具有相同的值。智能转换仅限于保证不会更改的内容,例如 val 本地模块中没有自定义 getter。

您可以使用

firstHashmap["foo"]?.let {
    secondHashmap["foo"] = it
}

仅在 secondHashmap 不为空时设置值。