在函数中从Hashmap正确返回Int

时间:2019-01-08 22:00:23

标签: dictionary kotlin return-value

我在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?>吗?

3 个答案:

答案 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
    }
}