从一开始,Kotlin就引入了范围(Range),以简化对连续数值集的操作——这继承了在处理数字时具有简洁语法的语言(例如Python)。此外,Range机制扩展到Progression,允许指定迭代步长并支持不同类型的数字和字符。
迭代整数、字母、时间点等通常需要特定的语法和标准库的可靠支持,否则代码会变得臃肿、难以阅读且容易在边界发生错误。
在Kotlin中,有标准类型IntRange、CharRange和LongRange,以及用于步进迭代的Progression。此外,可以为任意可比较类型定义范围。
// 简单范围 for (i in 1..5) print(i) // 12345 // 设定步长的范围 for (i in 1..10 step 2) print(i) // 13579 // 反向范围 for (i in 5 downTo 1) print(i) // 54321 // 自定义范围(例如,Version) data class Version(val major: Int, val minor: Int): Comparable<Version> { override fun compareTo(other: Version): Int = compareValuesBy(this, other, Version::major, Version::minor) } operator fun ClosedRange<Version>.iterator(): Iterator<Version> = object : Iterator<Version> { var current = start override fun hasNext() = current <= endInclusive override fun next() = current.also { current = Version(current.major, current.minor + 1) } } val v1 = Version(1, 0) val v2 = Version(1, 3) for (v in v1..v2) println(v)
关键特性:
.., downTo, until, step1..5与1 until 5有什么区别?
1..5包括范围的两个端点:1,2,3,4,5。1 until 5不包括最后一个元素:1,2,3,4。
可以使用step指定步长小于零的范围吗?
不可以。对于递减范围,请使用downTo结构,然后是step: 5 downTo 1 step 2(得到5,3,1)。
可以使用不实现Comparable的类型来定义范围吗?
不可以。定义范围需要类型支持比较。否则,编译器将不允许定义。
在代码中使用1 until n+1时代替了1..n。得到一个多余的元素,循环超出了允许的范围。
优点:
缺点:
使用for (i in 0 until n)来索引长度为n的数组,范围严格符合有效的索引值。
优点:
缺点: