🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 区间介绍 区间又叫Range,在数学里,区间通常是指一类实数集合,分为开区间、闭区间、半开半闭区间。 * 开区间指的是区间边界的两个值不包括在内,比如(a,b); * 闭区间指的是区间边界的两个值包括在内,[a,b] ; * 半开半闭区间指的是开区间一边的边界值不包括在内,闭区间一边的边界值包括在内,如下面的[a,b)、(a,b] * [a,b)被称作左闭右开区间,(a,b]被称作左开右闭区间。 Kotlin里面,对区间的表示提供了更加方便的支持。 在Kotlin里面,区间表示相关的类有IntRange、LongRange、CharRange,相关的接口有ClosedRange。这三个类都实现了ClosedRange接口,参考截图: ![](https://box.kancloud.cn/176c6868de5cf91f0b896933846bdeed_547x281.jpg) ## 区间表示 ### kotlin闭区间和左闭右开的表示 区间虽然分为开区间、闭区间、左开右闭区间、左闭右开。但是**Kotlin里面只支持“闭区间”和和“左闭右开”区间的表示**。**因为其实任何区间都可以转换为“闭区间”表示和“左闭右开”表示**: | **区间** | **案例** | **闭区间表示** | **左闭右开表示** | | ------ | ------ | --------- | ---------- | | 开区间 | (1,10) | [2,9] | [2,10) | | 闭区间 | [1,10] | [1,10] | [1,11) | | 左开右闭 | (1,10] | [2,10] | [2,11) | | 左闭右开 | [1,10) | [1,9] | [1,11) | Kotlin怎么**支持闭区间表示呢?**(可以通过下面的区间表示案例来了解这四种方法的用途)       * 一、可以**通过IntRange、LongRange、CharRange三个类的构造方法直接构造**, IntRange、LongRange、CharRange三个类的构造方法如下: ``` IntRange(start: Int, endInclusive: Int) LongRange(start: Long, endInclusive: Long) CharRange(start: Char, endInclusive: Char) ``` * 二、也可以**通过rangeTo方法生成**,rangeTo的方法定义如下: ![](http://upload-images.jianshu.io/upload_images/7368752-70c5e3148924ca9a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) >[info]PS:从下面从idea工具截图中,我们可以看出rangeTo存在于多个包中,多个kt文件中 ![](https://box.kancloud.cn/e4859854f10580d58bb7889348ccbeee_836x614.jpg) 当然,**rangeTo方法可以被“..操作符”替代**,后面我们讲了运算符重载你就会理解,现在可以先记住,下面两种形式是等价的: ``` val range1 = start.rangeTo(end) val range2 =start..end ``` >[info] 注意:上述代码中的start和end是对应的生成的不同区间的不同类型,比如生成IntRange则` val range1 = 2.rangeTo(9)`和`val range2 =2..9` **Kotlin怎么支持闭区间表示呢?**       通过拓展方法[until](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-ranges-index.html?lang=en)参考截图: 出自包[kotlin.ranges](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-ranges-index.html?lang=en)中的`_Ranges.kt`文件 ![](https://i.loli.net/2019/04/19/5cb8c0f2b0595.jpg) 通过截图,我们看到了很多的拓展方法,我们摘取其中一个方法的具体定义给大家看看: ~~~ public infix fun Int.until(to: Byte): IntRange { return this .. (to.toInt() - 1).toInt() } ~~~ ### **区间表示案例** * 一、kotlin表示“开区间(1,10)”可以有如下4种方式,参考代码: ~~~ fun main(args: Array<String>) { //开区间(1,10)的四种表示方法 val range11=IntRange(2,9) val range12=2.rangeTo(9) val range13=2..9 val range14=2 until 10 println(range11.toList()) println(range12.toList()) println(range13.toList()) println(range14.toList()) } ~~~ 运行结果 ``` [2, 3, 4, 5, 6, 7, 8, 9] [2, 3, 4, 5, 6, 7, 8, 9] [2, 3, 4, 5, 6, 7, 8, 9] [2, 3, 4, 5, 6, 7, 8, 9] Process finished with exit code 0 ``` * 二、kotlin表示“闭区间[1,10]”可以有如下方式,参考代码: ~~~ fun main(args: Array<String>) { // 闭区间[1,10]的四种表示方法 val range21=IntRange(1,10) val range22=1.rangeTo(10) val range23=1..10 val range24=1 until 11 println(range21.toList()) println(range22.toList()) println(range23.toList()) println(range24.toList()) } ~~~ 运行结果 ``` [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Process finished with exit code 0 ``` * 三、kotlin表示“左闭右开[1,10)”可以有如下方式,参考代码: ~~~ fun main(args: Array<String>) { //左闭右开区间[1,10)的四种表示方法 val range31=IntRange(1,9) val range32=1.rangeTo(9) val range33=1..9 val range34=1 until 10 println(range31.toList()) println(range32.toList()) println(range33.toList()) println(range34.toList()) } ~~~ 运行结果 ``` [1, 2, 3, 4, 5, 6, 7, 8, 9] [1, 2, 3, 4, 5, 6, 7, 8, 9] [1, 2, 3, 4, 5, 6, 7, 8, 9] [1, 2, 3, 4, 5, 6, 7, 8, 9] Process finished with exit code 0 ``` * 四、kotlin表示“左开右闭(1,10]”可以有如下方式,参考代码: ~~~ fun main(args: Array<String>) { //左开右闭区间(1,10]的四种表示方法 val range41=IntRange(2,10) val range42=2.rangeTo(10) val range43=2..10 val range44=2 until 11 println(range41.toList()) println(range42.toList()) println(range43.toList()) } ~~~ 运行结果 ``` [2, 3, 4, 5, 6, 7, 8, 9, 10] [2, 3, 4, 5, 6, 7, 8, 9, 10] [2, 3, 4, 5, 6, 7, 8, 9, 10] [2, 3, 4, 5, 6, 7, 8, 9, 10] Process finished with exit code 0 ``` ### 区间遍历 前面我们学习了如何定义区间,那**如何遍历区间中的元素呢**? 由于Range已经实现了Iterator接口,所以可以通过for循环遍历区间。 区间在for循环的时候,可以普通的for循环,还可以循环的时候调用step方法或者withIndex方法,参考代码: ~~~ /** * 区间遍历 */ fun main(args: Array<String>) { val charRange='a'..'d' println("---------普通for循环-------------") for(c in charRange){ println(c) } println("---------for循环 step-------------") for (c in charRange step 2){ println(c) } println("---------for循环 withIndex-------------") for (withIndex in charRange.withIndex()){ println("${withIndex.index} -> ${withIndex.value}") } println("---------for循环解析析构-------------") for ((index,value) in charRange.withIndex()){ println("${index}->${value}") } } ~~~ 运行结果 ``` ---------普通for循环------------- a b c d ---------for循环 step------------- a c ---------for循环 withIndex------------- 0 -> a 1 -> b 2 -> c 3 -> d ---------for循环解析析构------------- 0->a 1->b 2->c 3->d Process finished with exit code 0 ``` 除此之外,想要循环,我们还可以调用高阶函数,我们后面才学高阶函数,这里大家感受感受,后面再回过头来看看,代码如下: ~~~ fun main(args: Array<String>) { val charRange = 'a'..'d' println("----------forEach-----------") charRange.forEach() { println(it) } println("---------forEachIndexed---------") charRange.forEachIndexed { index, c -> println("$index->$c") } } ~~~ 运行结果 ``` ----------forEach----------- a b c d ---------forEachIndexed--------- 0->a 1->b 2->c 3->d Process finished with exit code 0 ``` ### 区间常见方法和属性 前面我们通过for循环遍历区间元素,但是我们想要获取区间第一个元素、最后一个元素的时候,kotlin为区间都有first、start和last属性。 ![](https://i.loli.net/2019/04/19/5cb8cd5a54d49.jpg) 想要**判断区间是否包含某一个元素的时候,可以使用contains**,参考代码: ~~~ fun main(args: Array<String>) { val charRange = 'a'..'d' val first = charRange.first val last = charRange.last val start = charRange.start println("第一个元素:$first") println("第一个元素:$start") println("最后一个元素:$last") println("是否包含元素a:${charRange.contains('a')}") } ~~~ 运行结果 ``` 第一个元素:a 第一个元素:a 最后一个元素:d 是否包含元素a:true Process finished with exit code 0 ``` 到现在为止,我们还不会高阶函数,后续章节会详细介绍高阶函数。我们先知道,区间也可以像数组和集合一样,可以使用大量的高阶函数进行操作,参考IDEA提示截图: ![](https://i.loli.net/2019/04/19/5cb967c47012a.png)