我在Kotlin中有一个函数,该函数接受一个Int
参数,并根据公式返回一个值。为了加快速度,我将中间结果存储在HashMap<Int, Int>
private val calculatedResults = HashMap<Int, Int>()
private fun q2(n: Int): Int {
if(calculatedResults.containsKey(n)) {
return calculatedResults[n]
}
val q = ...
calculatedResults[n] = q
return q
}
我在type mismatch of Int found but Int? required
上获得了
return calculatedResults[n]
我不确定如何正确编写此内容。我有
return calculatedResults[n]!!
但是我不确定,是否有点黑。
函数的返回类型应该为Int?
,因为尽管HashMap
可能包含键n
,但值却可能是null
?这不是说HashMap
应该是<Int, Int?>
吗?
答案 0 :(得分:1)
getOrPut将检查n
是否存在值。如果该值存在,它将被返回。如果值不存在,则将分配由lambda返回的值,然后由getOrPut
返回。
看看这个例子:
fun calculate(n: Int) = n * 5 // some calculation
private fun q2(n: Int) = calculatedResults.getOrPut(n) {
calculate(n)
}
函数的返回类型应该为Int吗?因为虽然 HashMap可能包含键n,值可以为null?那不是吗 HashMap应该是?
在这种情况下,问题的答案显然是“否”,因为如果缺少该值,则只需将其添加即可。因此,q2
返回的值永远不会是null
。
答案 1 :(得分:0)
潜在的问题是calculatedResults
可能已被包含({if(calculatedResults.containsKey(n))
)和get(return calculatedResults[n]
)之间的其他线程修改。
因此即使在使用containsKey
calculatedResults[n]
检查之后,也可能返回错误的结果,包括null
,因此应避免这种检查方式。
通常仅在绝对必要时才使用!!
,因为它会导致NPE。绝对是hacky。
使用以下语法克服该问题:
calculatedResults[n]?.let {
return it
}
基本上,这是一种很好的表达方式
val result = calculatedResults[n]
if(result != null) {
return result
}
请参阅https://kotlinlang.org/docs/reference/null-safety.html#safe-calls
更好的方法是使用内置的getOrPut:
private fun q2(n: Int): Int {
return calculatedResults.getOrPut(n) { calcQ() }
}
private fun calcQ(): Int {
val q = ...
return q
}
函数的返回类型应该为Int?
,因为尽管HashMap
可能包含键n,但该值可能为null?这不是说HashMap
应该是<Int, Int?>
吗?
不,您在定义方法签名时所做的事情完全正确。编译器仅抱怨是因为方法中发生的事情不适合它。如果更改方法签名,则只需将问题移至调用q2
的函数即可,而无需对其进行处理。
答案 2 :(得分:0)
您应该考虑将其重写为更多惯用的代码。如果尚未在地图中设置值,则计算值是一项相当基本的任务:
fun q2(n: Int): Int {
return calculatedResults.getOrPut(n) {
42 //q
}
}