我正在使用 when
语句来检查变量是否在多个相当大的范围内。
为简单起见,我的代码如下所示:
val lowRange = Int.MIN_VALUE..0
val mediumRange = 1..999_999
//...
val valToCheck = 1_000_000
when (valToCheck) {
in lowRange -> { doSomething() }
in mediumRange -> { doSomethingElse() }
//...
else -> { handleTooHighOrNull() }
}
这很好用;但是,当我使 valToCheck 可为空时:
val lowRange = Int.MIN_VALUE..0
val mediumRange = 1..999_999
//...
val valToCheck = if(someCondition) { 1_000_000 } else { null }
when (valToCheck) {
in lowRange -> { doSomething() }
in mediumRange -> { doSomethingElse() }
//...
else -> { handleTooHighOrNull() }
}
我的应用程序完全卡住。
减小范围的大小确实解决了这个问题,就像在第一种情况下使 valToCheck 不可为空或检查空值一样,但我一定在这里遗漏了一些东西:
为什么会这样?
in
运算符真的只是遍历范围内的每个数字并将其与给定值进行比较吗?如果它实际上是遍历范围内的每个值,为什么它只对可空的 Int 这么慢? (就此而言,为什么这在任何地方都没有记录,因为这看起来应该是一个相当常见的用例?)
有没有更易读的方法来做到这一点?
如果有这样的东西我会很高兴:
when(valToCheck) {
< 0 -> { doSomething() }
< 500 -> { doSomethingElse() }
//...
else -> { handleTooHighOrNull() }
}
但这似乎是不可能的,事实上,搜索是让我首先使用范围的原因。
如果有任何建议,我将不胜感激。谢谢!
最佳答案
如果我们看到 IntRange
的实现, in
可空运算符 Int
未定义 - 因此它回落到 Iterable<T>.contains()
.
对于 Int
s - O(1):
public class IntRange(start: Int, endInclusive: Int) : IntProgression(start, endInclusive, 1), ClosedRange<Int> {
...
override fun contains(value: Int): Boolean = first <= value && value <= last
...
}
对于 Int?
s - O(n):
public operator fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.contains(element: T): Boolean {
if (this is Collection)
return contains(element)
return indexOf(element) >= 0
}
您可以通过制作如下扩展函数来解决此问题:
operator fun IntRange.contains(value: Int?): Boolean {
return if (value != null) {
first <= value && value <= last
} else false
}
这将确定给定是否可为空 Int
在一些IntRange
在 O(1) 时间内。
关于android - 当给定可空 Int 时,具有大范围的 Kotlin when 语句卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51433444/