Kotlin 具有hashmap键的智能Cast

Kotlin 具有hashmap键的智能Cast,kotlin,nullable,Kotlin,Nullable,我正在将一些Java应用程序移植到Kotlin,我一直在使用hashmaps解决这个问题。假设我有两个哈希映射: var firstHashmap: HashMap<String, String> = hashMapOf("foo" to "A", "bar" to "B") var secondHashmap: HashMap<String, String> = hashMapOf(&quo

我正在将一些Java应用程序移植到Kotlin,我一直在使用hashmaps解决这个问题。假设我有两个哈希映射:

var firstHashmap: HashMap<String, String> = hashMapOf("foo" to "A", "bar" to "B")
var secondHashmap: HashMap<String, String> = hashMapOf("foo" to "C", "bar" to "D")
Kotlin不会编译第二行,因为firstHashmap不能保证有一个foo键。我只是在第一行检查了它,这并不重要——smart cast系统显然不能使用hashmap键。这也有同样的问题:

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"] ?: ""
有没有更好的方法来处理这个问题,比如触发智能cast系统知道钥匙真的在那里?否则我猜是!!选项似乎最干净,特别是当我从上一行清楚地知道为什么选择使用它时。

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

你可以用

firstHashmap["foo"]?.let {
    secondHashmap["foo"] = it
}
仅设置secondHashmap上的值(如果该值不为null)。

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

你可以用

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

如果secondHashmap不为null,则仅在其上设置值。

如果hashmap是在本地定义的,其值如何在代码的第一行和第二行之间更改?在任何情况下,您的解决方案对我都有效。@arlomedia如果生成一个本地线程,在2ms后更改值,并且在if检查中执行了一些耗时5ms的阻塞调用,将会发生什么。那么当你设置这个值时,它可能会变成空的,不是吗?@AnimeshSahu谢谢。我并没有做任何类似的事情,但现在我明白了为什么编译器会保护它!!你可以告诉编译器不,这绝对不是空的,不用担心。你在为编译器无法证明自己的东西做保证,而你必须确保这永远是真的。使用vars时,您更有可能再次遇到这种情况,因为在您检查该值后,另一个线程可能会更改该值,因此存在争用条件,通常的kotlin方法是go thing?。让{doSomethingWithit}将该值分配给默认情况下称为它的临时val,该值保证不会更改。如果hashmap是本地定义的,那么它的值在代码的第一行和第二行之间如何变化?在任何情况下,您的解决方案对我都有效。@arlomedia如果生成一个本地线程,在2ms后更改值,并且在if检查中执行了一些耗时5ms的阻塞调用,将会发生什么。那么当你设置这个值时,它可能会变成空的,不是吗?@AnimeshSahu谢谢。我并没有做任何类似的事情,但现在我明白了为什么编译器会保护它!!你可以告诉编译器不,这绝对不是空的,不用担心。你在为编译器无法证明自己的东西做保证,而你必须确保这永远是真的。使用vars时,您更有可能再次遇到这种情况,因为在您检查该值后,另一个线程可能会更改该值,因此存在争用条件,通常的kotlin方法是go thing?。让{doSomethingWithit}将该值分配给默认情况下称为它的临时val,该值保证不会更改。还有map.getOrDefault