android - 当给定可空 Int 时,具有大范围的 Kotlin when 语句卡住

标签 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() }
}

这很好用;但是,当我使 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/

相关文章:

android - 如何从 fragment 中捕获导航图标单击工具栏?

java - 此 NavController 不知道操作

android - 修饰符工厂函数不应标记为@Composable

kotlin - 按给定值而不是 KEY 检索枚举

java - Android:如何在应用程序进行其他工作时连续保存传感器数据

android - 从 SQLite 数据库中获取 Blob

android - 将 Monkeyrunner 与 UI Automator 集成

java - 尽管这是一个 kotlin 类,为什么我们要编写 NextActivity::class.java ?

java - 如何在 Java/Kotlin 中创建返回复杂类型的 Spark UDF?

Android - 是否可以通过编程方式访问 androidTest 和测试文件夹中的工具化测试和单元测试类?