Kotlin当大范围语句冻结时给出可以为空的Int

ajp*_*olt 3 android kotlin

我正在使用一个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() }
}
Run Code Online (Sandbox Code Playgroud)

这很好用; 但是,当我使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() }
}
Run Code Online (Sandbox Code Playgroud)

我的应用程序完全冻结.

减小范围的大小确实解决了问题,就像使valToCheck不可为空或检查空值作为第一种情况一样,但我必须在这里遗漏一些东西:

  • 为什么会这样?in操作员是否真的只是迭代一个范围内的每个数字并将其与给定值进行比较?

  • 如果它实际上迭代了范围中的每个值,为什么它对于可空的Ints来说只是如此慢?(对于这个问题,为什么这里没有记录,因为这似乎应该是一个相当常见的用例?)

  • 有更可读的方法吗?

我喜欢它,如果有类似的东西:

when(valToCheck) {
    < 0 -> { doSomething() }
    < 500 -> { doSomethingElse() }
    //...
    else -> { handleTooHighOrNull() }
}
Run Code Online (Sandbox Code Playgroud)

但这似乎是不可能的,事实上,寻找这一点是让我首先使用范围的原因.

我会非常感谢任何建议.谢谢!

shi*_*psh 6

如果我们看到实现IntRange,那么innullable的operator Int不会被定义 - 因此它会回归到Iterable<T>.contains().


对于Ints - 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
    ...
}
Run Code Online (Sandbox Code Playgroud)

对于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
}
Run Code Online (Sandbox Code Playgroud)

您可以通过制作扩展功能来解决此问题:

operator fun IntRange.contains(value: Int?): Boolean {
    return if (value != null) {
        first <= value && value <= last
    } else false
} 
Run Code Online (Sandbox Code Playgroud)

这将确定给定的可空值Int是否IntRange在O(1)时间内.