希望帮你在Kotlin进阶路上少走弯路,在技术上稳步提升。当然,由于个人知识储备有限,笔记中难免存在疏漏或表述不当的地方,也非常欢迎大家提出宝贵意见,一起交流进步。 ------ Android_小雨
整体目录:Kotlin 进阶不迷路:41 个核心知识点,构建完整知识体系
一、前言
1.1 循环在开发中的核心作用(遍历数据、重复执行逻辑)
循环是编程中最基础也最核心的流程控制结构之一,几乎所有开发场景都离不开它。其核心作用主要体现在两个方面:一是遍历数据 ,无论是数组、列表、集合还是字符串,我们都需要通过循环逐个访问其中的元素,实现数据的读取、筛选、转换等操作,比如遍历用户列表获取所有用户名、遍历订单数据统计总金额;二是重复执行逻辑,当一段代码需要多次执行时,循环能避免冗余的重复编写,只需定义一次逻辑即可指定执行次数或执行条件,比如批量创建10个测试用户、每隔1秒打印一次系统状态等。
以Java中遍历1到10的循环为例,传统写法需要定义循环变量、初始值、终止条件和步长,代码略显繁琐。而Kotlin通过"for循环+区间"的组合,将循环逻辑优化得极为简洁直观,让开发者能更专注于业务逻辑而非循环结构本身。
1.2 Kotlin for 循环 + 区间的优势(简洁、直观、功能强大)
Kotlin并没有沿用Java中for循环的"三段式"语法(for(int i=0; i<10; i++)),而是对for循环进行了重构,使其成为一种"迭代器遍历"的语法糖,尤其与Kotlin特有的"区间(Range)"结合后,展现出三大核心优势:
- 极致简洁:无需手动定义循环变量、终止条件和步长,通过区间表达式即可快速描述循环范围,一行代码就能实现常见的遍历需求,比如遍历1到10只需"for (i in 1..10)"。
- 直观易懂:区间表达式的语法贴近自然语言,"1..5"表示"从1到5的闭区间","1 until 5"表示"从1到5但不包含5","10 downTo 1"表示"从10倒序到1",即使是新手也能一眼看懂循环范围。
- 功能强大:支持正序、倒序、指定步长遍历,还能直接与数组、列表等集合配合,同时兼容字符区间等特殊场景,覆盖绝大多数循环需求。
同样是遍历1到10并打印,对比Java和Kotlin的写法就能直观感受到其优势:
java
// Java 传统 for 循环
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
kotlin
// Kotlin for 循环 + 区间
for (i in 1..10) {
println(i)
}
1.3 本文核心内容预告(区间基础→for 循环用法→实用场景)
本文将围绕"for循环与区间"展开,采用"基础先行、用法递进、场景落地"的思路逐步讲解。首先从Kotlin区间的基础概念入手,介绍区间的定义、三种核心类型(闭区间、半开区间、倒序区间)以及步长的使用方法;接着重点讲解for循环与区间的配合用法,覆盖正序、不包含终点、倒序、指定步长等常见遍历场景,同时拓展到for循环遍历数组、列表等其他集合的用法;然后通过多个实用场景案例,展示"for循环+区间"在实际开发中的应用;最后总结核心知识点、适用场景和避坑技巧,帮助读者真正掌握这一简洁高效的循环方式。
二、先搞懂:Kotlin 区间 (Range) 基础
2.1 什么是区间?(连续值的集合,如数字 / 字符区间)
在Kotlin中,区间(Range)是一种表示"连续值集合"的数据结构,它本质上是实现了ClosedRange接口的类,用于描述从一个起始值到一个结束值的连续范围。区间中的元素必须是可比较的(实现Comparable接口),常见的区间类型包括数字区间(如IntRange、LongRange)和字符区间(CharRange),比如"1到5的数字区间"包含1、2、3、4、5五个值,"A到E的字符区间"包含A、B、C、D、E五个字符。
区间的核心价值在于"简化范围的描述",它将"起始值、结束值、增减方向"等信息封装为简洁的表达式,配合for循环使用时能极大简化遍历逻辑。需要注意的是,Kotlin的区间默认是"连续且有序"的,不支持非连续的离散值范围(如1、3、5这样的奇数集合,需通过其他方式实现)。
2.2 区间的基本语法(闭区间..、半开区间 until、倒序区间 downTo)
Kotlin提供了三种核心的区间定义语法,分别对应不同的遍历需求,掌握这三种语法是使用区间的基础:
2.2.1 闭区间:.. (包含起始值和结束值)
用"起始值..结束值"的语法定义闭区间,表示包含起始值和结束值在内的所有连续值。这是最常用的区间类型,适用于需要遍历"从a到b(含a和b)"的场景。
kotlin
// 数字闭区间:1到5,包含1、2、3、4、5
val intRange = 1..5
// 字符闭区间:'A'到'E',包含'A'、'B'、'C'、'D'、'E'
val charRange = 'A'..'E'
// 长整型闭区间:100L到105L
val longRange = 100L..105L
2.2.2 半开区间:until (包含起始值,不包含结束值)
用"起始值 until 结束值"的语法定义半开区间,表示包含起始值但不包含结束值的连续值。这种区间类型与Java中"i < 结束值"的逻辑一致,适用于避免"结束值-1"的繁琐计算场景,比如遍历数组(数组索引从0开始,到长度-1结束)。
kotlin
// 数字半开区间:1 until 5,包含1、2、3、4(不包含5)
val halfOpenRange = 1 until 5
// 字符半开区间:'a' until 'd',包含'a'、'b'、'c'(不包含'd')
val charHalfOpenRange = 'a' until 'd'
2.2.3 倒序区间:downTo (从结束值倒序到起始值)
用"结束值 downTo 起始值"的语法定义倒序区间,表示从结束值开始,倒序遍历到起始值(包含起始值和结束值)。传统循环中倒序遍历需要手动调整循环变量,而downTo语法让倒序逻辑一目了然。
kotlin
// 数字倒序区间:5 downTo 1,包含5、4、3、2、1
val reverseRange = 5 downTo 1
// 字符倒序区间:'E' downTo 'A',包含'E'、'D'、'C'、'B'、'A'
val charReverseRange = 'E' downTo 'A'
2.3 常用区间示例(数字区间、字符区间、步长 step 用法)
除了三种基础区间类型,Kotlin还支持通过"step"关键字指定区间的遍历步长(即每次递增或递减的数值),默认步长为1。步长可以是正数(正序区间)或负数(倒序区间,但通常用downTo更直观),适用于需要"跳跃式"遍历的场景。下面通过具体示例展示数字区间、字符区间和步长的用法:
2.3.1 数字区间示例
kotlin
fun main() {
// 1. 闭区间:1到5,步长默认1
val closedRange = 1..5
println("闭区间 1..5:${closedRange.toList()}") // 输出:闭区间 1..5:[1, 2, 3, 4, 5]
// 2. 半开区间:1到5(不含5),步长默认1
val halfOpenRange = 1 until 5
println("半开区间 1 until 5:${halfOpenRange.toList()}") // 输出:半开区间 1 until 5:[1, 2, 3, 4]
// 3. 倒序区间:5到1,步长默认1
val reverseRange = 5 downTo 1
println("倒序区间 5 downTo 1:${reverseRange.toList()}") // 输出:倒序区间 5 downTo 1:[5, 4, 3, 2, 1]
// 4. 指定步长的正序区间:1到10,步长2(只取奇数)
val stepRange = 1..10 step 2
println("步长2的正序区间:${stepRange.toList()}") // 输出:步长2的正序区间:[1, 3, 5, 7, 9]
// 5. 指定步长的倒序区间:10到1,步长3
val reverseStepRange = 10 downTo 1 step 3
println("步长3的倒序区间:${reverseStepRange.toList()}") // 输出:步长3的倒序区间:[10, 7, 4, 1]
}
2.3.2 字符区间示例
字符区间基于字符的ASCII码值进行排序,支持正序、倒序和步长遍历,适用于需要遍历字母表等场景:
kotlin
fun main() {
// 1. 正序字符闭区间:'a'到'e'
val lowerCharRange = 'a'..'e'
println("小写字母区间:${lowerCharRange.toList()}") // 输出:小写字母区间:[a, b, c, d, e]
// 2. 倒序字符区间:'Z'到'W'
val upperReverseRange = 'Z' downTo 'W'
println("倒序大写字母区间:${upperReverseRange.toList()}") // 输出:倒序大写字母区间:[Z, Y, X, W]
// 3. 指定步长的字符区间:'A'到'I',步长2(取A、C、E、G、I)
val charStepRange = 'A'..'I' step 2
println("步长2的字符区间:${charStepRange.toList()}") // 输出:步长2的字符区间:[A, C, E, G, I]
}
2.3.3 步长使用注意事项
步长的使用虽然灵活,但有两个关键点需要注意:一是步长不能为0 ,否则会导致无限循环,Kotlin编译器会直接报错;二是倒序区间建议用downTo配合正步长,而非用正序区间配合负步长(虽然语法允许,但可读性极差)。
kotlin
fun main() {
// 错误示例:步长为0,编译报错
// val errorRange = 1..5 step 0
// 不推荐:正序区间配合负步长(可读性差)
val notRecommended = 5..1 step -1
println(notRecommended.toList()) // 输出:[5, 4, 3, 2, 1]
// 推荐:用downTo定义倒序区间,配合正步长(可读性高)
val recommended = 5 downTo 1 step 1
println(recommended.toList()) // 输出:[5, 4, 3, 2, 1]
}
三、Kotlin for 循环:与区间的完美配合
3.1 for 循环的基本语法(遍历区间的简洁写法)
Kotlin的for循环摒弃了Java中"三段式"的复杂语法,采用"for (元素变量 in 可迭代对象)"的简洁形式,其中"可迭代对象"可以是区间、数组、列表、集合等实现了Iterable接口的类型。当可迭代对象是区间时,for循环会逐个遍历区间中的元素,语法如下:
kotlin
// for 循环遍历区间的基本语法
for (element in 区间表达式) {
// 循环体:element 为当前遍历到的区间元素
执行逻辑
}
这种语法的优势在于"聚焦元素本身",无需关注循环变量的初始化、终止条件和步长调整(区间已封装这些信息),比如遍历1到5并打印每个元素,只需一行循环头即可实现:
kotlin
fun main() {
// 遍历1到5的闭区间,打印每个元素
for (i in 1..5) {
print("$i ") // 输出:1 2 3 4 5
}
}
3.2 遍历常见区间场景
结合上一章讲解的三种区间类型和步长用法,for循环与区间配合可实现多种常见的遍历场景,下面分别介绍并给出示例。
3.2.1 正序遍历(如 1..5 遍历 1-5)
正序遍历是最基础的场景,使用闭区间"起始值..结束值"即可,默认步长为1,适用于需要从起始值到结束值依次遍历的场景,比如打印1到10的数字、遍历字母表等。
kotlin
fun main() {
// 场景1:打印1到10的正整数
println("1到10的正整数:")
for (num in 1..10) {
print("$num ") // 输出:1 2 3 4 5 6 7 8 9 10
}
println()
// 场景2:打印A到F的大写字母
println("A到F的大写字母:")
for (char in 'A'..'F') {
print("$char ") // 输出:A B C D E F
}
}
3.2.2 不包含终点遍历(until 关键字)
当需要遍历"从起始值到结束值,但不包含结束值"时,使用半开区间"起始值 until 结束值",这种场景在遍历数组、列表等索引从0开始的集合时尤为常用,能避免"索引越界"的风险。
kotlin
fun main() {
// 场景1:遍历0到4(不包含5),模拟数组索引
val array = arrayOf("Kotlin", "Java", "Python", "Go", "Swift")
println("数组元素:")
// 数组长度为5,索引范围0-4,用until避免索引越界
for (index in 0 until array.size) {
println("索引$index:${array[index]}")
}
// 输出:
// 索引0:Kotlin
// 索引1:Java
// 索引2:Python
// 索引3:Go
// 索引4:Swift
// 场景2:打印1到9(不包含10)的数字
println("1到9的数字:")
for (num in 1 until 10) {
print("$num ") // 输出:1 2 3 4 5 6 7 8 9
}
}
3.2.3 倒序遍历(downTo 关键字)
倒序遍历使用"结束值 downTo 起始值"的倒序区间,适用于需要从大到小遍历的场景,比如倒计时、逆序打印数据等。相比传统循环的倒序写法,downTo语法更直观。
kotlin
fun main() {
// 场景1:倒计时(10到1)
println("倒计时开始:")
for (count in 10 downTo 1) {
print("$count ")
Thread.sleep(1000) // 模拟延迟1秒
}
println("!倒计时结束") // 输出:10 9 8 7 6 5 4 3 2 1 !倒计时结束
// 场景2:逆序打印数组元素
val numbers = arrayOf(10, 20, 30, 40, 50)
println("数组逆序元素:")
for (index in numbers.size - 1 downTo 0) {
print("${numbers[index]} ") // 输出:50 40 30 20 10
}
}
3.2.4 指定步长遍历(step 控制间隔)
当需要"跳跃式"遍历区间时,在区间表达式后加上"step 步长值"即可,适用于只需要遍历区间中部分元素的场景,比如遍历奇数、偶数,或每隔n个元素处理一次。
kotlin
fun main() {
// 场景1:遍历1到20的偶数(步长2,起始值为2)
println("1到20的偶数:")
for (even in 2..20 step 2) {
print("$even ") // 输出:2 4 6 8 10 12 14 16 18 20
}
println()
// 场景2:遍历100到50的整十数(倒序,步长10)
println("100到50的整十数:")
for (ten in 100 downTo 50 step 10) {
print("$ten ") // 输出:100 90 80 70 60 50
}
println()
// 场景3:每隔3个字母打印一次(A到Z,步长3)
println("A到Z每隔3个字母:")
for (char in 'A'..'Z' step 3) {
print("$char ") // 输出:A D G J M P S V Y
}
}
3.3 for 循环遍历其他集合(结合区间思想遍历数组、列表)
虽然Kotlin的for循环与区间配合极为默契,但它并非只能遍历区间。实际上,for循环可以遍历所有实现了Iterable接口的集合(如数组、List、Set等),其核心思想与遍历区间一致------"逐个访问集合中的元素"。下面介绍两种常见的集合遍历场景:直接遍历元素和通过索引遍历元素(结合区间思想)。
3.3.1 直接遍历集合元素
对于数组、List等集合,for循环可以直接遍历其中的元素,无需通过索引,语法为"for (元素 in 集合)",这种方式最简洁,适用于不需要关注元素索引的场景。
kotlin
fun main() {
// 1. 遍历数组元素
val fruits = arrayOf("苹果", "香蕉", "葡萄", "橙子")
println("水果数组:")
for (fruit in fruits) {
println("水果:$fruit")
}
// 输出:
// 水果:苹果
// 水果:香蕉
// 水果:葡萄
// 水果:橙子
// 2. 遍历List元素
val scores = listOf(85, 92, 78, 95, 88)
println("成绩列表:")
var total = 0
for (score in scores) {
total += score
}
println("总成绩:$total,平均分:${total / scores.size}") // 输出:总成绩:438,平均分:87
}
3.3.2 通过索引遍历集合元素(结合区间)
当需要同时获取元素的索引和值时,可以结合区间思想,通过"0 until 集合.size"的半开区间遍历索引,再通过索引获取元素。这种方式类似于Java中的"for循环遍历索引",但语法更简洁。
kotlin
fun main() {
// 遍历数组:同时获取索引和元素
val colors = arrayOf("红色", "绿色", "蓝色", "黄色")
println("颜色数组(索引-值):")
for (index in 0 until colors.size) {
val color = colors[index]
println("索引$index:$color")
}
// 输出:
// 索引0:红色
// 索引1:绿色
// 索引2:蓝色
// 索引3:黄色
// 遍历List:倒序获取索引和元素
val names = listOf("张三", "李四", "王五")
println("姓名列表(逆序索引-值):")
for (index in names.size - 1 downTo 0) {
println("索引$index:${names[index]}")
}
// 输出:
// 索引2:王五
// 索引1:李四
// 索引0:张三
}
此外,Kotlin还提供了"withIndex()"方法,可直接获取包含索引和值的Pair对象,进一步简化"索引+值"的遍历逻辑:
kotlin
fun main() {
val languages = listOf("Kotlin", "Java", "Python")
for ((index, lang) in languages.withIndex()) {
println("索引$index:$lang")
}
// 输出:
// 索引0:Kotlin
// 索引1:Java
// 索引2:Python
}
四、for 循环 + 区间 实用场景举例
"for循环+区间"的组合在实际开发中应用广泛,无论是简单的数字遍历,还是复杂的业务数据处理,都能发挥其简洁高效的优势。下面通过四个常见的实用场景,展示其在开发中的具体应用。
4.1 数字遍历(如循环打印 1-10)
数字遍历是最基础的场景,常用于打印连续数字、生成连续数据、计数等需求。下面以"生成1到100的奇数并计算总和"为例,展示数字遍历的应用:
kotlin
/**
* 场景:生成1到100的奇数,打印并计算总和
*/
fun generateOddNumbers() {
val oddList = mutableListOf<Int>()
var total = 0
// 遍历1到100,步长2,获取所有奇数
for (num in 1..100 step 2) {
oddList.add(num)
total += num
}
println("1到100的奇数共有${oddList.size}个:")
println(oddList.take(10).joinToString(", ") + "..." + oddList.takeLast(10).joinToString(", "))
println("1到100的奇数总和:$total")
}
fun main() {
generateOddNumbers()
// 输出:
// 1到100的奇数共有50个:
// 1, 3, 5, 7, 9, 11, 13, 15, 17, 19...81, 83, 85, 87, 89, 91, 93, 95, 97, 99
// 1到100的奇数总和:2500
}
4.2 字符遍历(如循环打印 A-Z)
字符遍历常用于生成字母表、字符编码转换、批量生成字符串等场景。下面以"生成A-Z的大写字母和对应的ASCII码"为例,展示字符遍历的应用:
kotlin
/**
* 场景:生成A-Z的大写字母,打印字母及对应的ASCII码
*/
fun printCharAndAscii() {
println("大写字母 | ASCII码")
println("--------|--------")
// 遍历'A'到'Z'的字符区间
for (char in 'A'..'Z') {
val ascii = char.toInt() // 获取字符的ASCII码
println("$char | $ascii")
}
}
fun main() {
printCharAndAscii()
// 输出(部分):
// 大写字母 | ASCII码
// --------|--------
// A | 65
// B | 66
// C | 67
// ...
// Z | 90
}
4.3 集合遍历(如遍历列表、数组)
集合遍历是开发中最常用的场景之一,常用于数据筛选、转换、统计等操作。下面以"遍历学生列表,筛选出成绩≥90分的优秀学生并排序"为例,展示集合遍历的应用:
kotlin
// 定义学生数据类
data class Student(val name: String, val score: Int)
/**
* 场景:遍历学生列表,筛选优秀学生并排序
*/
fun filterExcellentStudents() {
// 模拟学生列表数据
val students = listOf(
Student("张三", 85),
Student("李四", 92),
Student("王五", 78),
Student("赵六", 95),
Student("钱七", 88),
Student("孙八", 90)
)
val excellentStudents = mutableListOf<Student>()
// 遍历学生列表,筛选成绩≥90分的学生
for (student in students) {
if (student.score >= 90) {
excellentStudents.add(student)
}
}
// 按成绩降序排序(通过索引遍历排序后的列表)
val sortedStudents = excellentStudents.sortedByDescending { it.score }
println("优秀学生列表(成绩≥90分,按成绩降序):")
for (index in 0 until sortedStudents.size) {
val student = sortedStudents[index]
println("第${index + 1}名:${student.name},成绩:${student.score}")
}
}
fun main() {
filterExcellentStudents()
// 输出:
// 优秀学生列表(成绩≥90分,按成绩降序):
// 第1名:赵六,成绩:95
// 第2名:李四,成绩:92
// 第3名:孙八,成绩:90
}
4.4 简单业务场景(如计数、批量处理数据)
在实际业务中,"for循环+区间"可用于批量处理数据、计数统计、生成测试数据等场景。下面以"批量生成10个测试用户并统计男性用户数量"为例,展示其业务应用:
kotlin
// 定义用户数据类
data class User(val id: Int, val name: String, val gender: String)
/**
* 场景:批量生成10个测试用户,统计男性用户数量
*/
fun generateTestUsers() {
val users = mutableListOf<User>()
var maleCount = 0
// 遍历1到10的区间,生成10个用户
for (id in 1..10) {
val name = "测试用户$id"
// 奇数ID为男性,偶数ID为女性
val gender = if (id % 2 == 1) "男" else "女"
val user = User(id, name, gender)
users.add(user)
// 统计男性用户数量
if (gender == "男") {
maleCount++
}
}
// 打印所有用户信息
println("批量生成的10个测试用户:")
for (user in users) {
println("ID:${user.id},姓名:${user.name},性别:${user.gender}")
}
println("男性用户数量:$maleCount,女性用户数量:${users.size - maleCount}")
}
fun main() {
generateTestUsers()
// 输出(部分):
// 批量生成的10个测试用户:
// ID:1,姓名:测试用户1,性别:男
// ID:2,姓名:测试用户2,性别:女
// ...
// ID:10,姓名:测试用户10,性别:女
// 男性用户数量:5,女性用户数量:5
}
五、总结与使用建议
5.1 核心知识点回顾(区间类型、for 循环遍历方式)
- 区间核心知识点:区间是连续值的集合,支持三种类型------闭区间(..,包含首尾)、半开区间(until,包含首不包含尾)、倒序区间(downTo,从尾到首);可通过step指定步长(默认1,不能为0),支持数字和字符区间。
- for循环核心知识点:采用"for (元素 in 可迭代对象)"的简洁语法,可遍历区间、数组、列表等集合;遍历区间时无需关注循环变量细节,聚焦元素本身;遍历集合时支持直接遍历元素或通过索引遍历(结合区间)。
- 组合优势:"for循环+区间"实现了循环逻辑的极致简化,将"范围描述"与"遍历执行"完美结合,语法直观、可读性高,覆盖绝大多数循环场景。
5.2 适用场景与避坑点(何时用哪种区间、步长注意事项)
5.2.1 适用场景与区间选择
- 正序遍历且包含首尾值:选择闭区间"a..b",如遍历1到10的所有数字。
- 正序遍历且不包含尾值:选择半开区间"a until b",如遍历数组索引(0 until 数组.size)。
- 倒序遍历:选择倒序区间"b downTo a",如倒计时、逆序打印数据。
- 跳跃式遍历:在上述区间基础上添加"step 步长",如遍历奇数(1..100 step 2)。
- 集合遍历:直接遍历元素用"for (元素 in 集合)";需要索引用"for (index in 0 until 集合.size)"或"for ((index, 元素) in 集合.withIndex())"。
5.2.2 避坑点
- 步长不可为0:步长为0会导致无限循环,编译器会直接报错,务必确保步长为非0整数。
- 倒序遍历避免负步长:倒序遍历推荐用"downTo"配合正步长,而非正序区间配合负步长,提升代码可读性。
- 字符区间注意ASCII码顺序:字符区间基于ASCII码排序,大写字母ASCII码小于小写字母(如'A'..'z'会包含其他字符),需谨慎使用跨大小写的字符区间。
- 区间不可直接用于非连续值:区间仅支持连续值,若需遍历非连续值(如1、3、5、7),可通过步长实现,或使用集合存储非连续值后遍历。
5.3 代码简洁性技巧(用区间简化循环逻辑)
- 替代传统计数循环:摒弃Java"三段式"循环,所有计数循环都用"for (i in 区间)"实现,如"for (i in 1..10)"替代"for (int i=1; i<=10; i++)"。
- 利用区间生成集合:通过"区间.toList()"快速生成连续值集合,如"(1..5).toList()"生成[1,2,3,4,5],避免手动添加元素。
- 结合集合函数简化逻辑:遍历集合时,若需筛选、转换数据,可结合Kotlin集合函数(如filter、map),减少for循环内的复杂逻辑。例如,筛选成绩≥90的学生可简化为"students.filter { it.score ≥ 90 }"。
- 单语句循环省略花括号:若循环体仅包含一条语句,可省略花括号,进一步简化代码,如"for (i in 1..5) print(i)"。
Kotlin的"for循环+区间"是对传统循环语法的一次重要优化,其核心在于"用简洁的语法描述复杂的循环范围",让开发者能更专注于业务逻辑。掌握区间的三种类型、步长的使用以及for循环与不同可迭代对象的配合,能极大提升代码的简洁性和可读性。建议在开发中主动摒弃传统的"三段式"循环思维,多用"for循环+区间"的组合,逐步养成Kotlin式的简洁编码习惯。