我正在使用when语句来检查变量是否在很多相当大的范围内. 为了简单起见,我的代码看起来像: val lowRange = Int.MIN_VALUE..0val mediumRange = 1..999_999//...val valToCheck = 1_000_000when (valToCheck) { in lo
为了简单起见,我的代码看起来像:
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运算符是否真的遍历范围中的每个数字并将其与给定值进行比较?
>如果它实际上是遍历范围内的每个值,为什么它对于可空的Ints来说只是如此慢? (对于这个问题,为什么这里没有记录,因为这似乎应该是一个相当常见的用例?)
>有更可读的方法吗?
我喜欢它,如果有类似的东西:
when(valToCheck) { < 0 -> { doSomething() } < 500 -> { doSomethingElse() } //... else -> { handleTooHighOrNull() } }
但这似乎是不可能的,事实上,寻找这一点是让我首先使用范围的原因.
我会非常感谢任何建议.谢谢!
如果我们看到IntRange的实现,则在未定义的可操作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 ... }
对于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是否在O(1)时间内在某个IntRange中.