1. 简介

循环是编程语言中最基础的控制结构之一,它允许我们在满足特定条件时重复执行一段代码。

本文将系统介绍 Kotlin 支持的几种循环类型:

  • repeat
  • for 循环
  • while 循环
  • do..while 循环

我们从最简单的 repeat 开始讲起。对于有经验的开发者来说,这部分内容虽然基础,但在某些场景下非常实用,比如快速执行某段逻辑 N 次而无需手动维护计数器。

2. repeat 循环

repeat 是 Kotlin 中最简洁的循环形式,适用于明确知道执行次数的场景。

例如,打印两次 "Hello World":

repeat(2) {
    println("Hello World")
}

更进一步,你还可以获取当前迭代的索引(从 0 开始):

repeat(2) { index ->
    println("第 ${index + 1} 次:Hello World")
}

⚠️ 注意:repeat 的参数必须是非负整数,传入负数会抛出 IllegalArgumentException —— 这是个容易踩坑的地方,调用前最好做校验。

3. for 循环

Kotlin 的 for 循环语法如下:

for (变量 in 表达式) {
    // 执行语句
}

核心能力for 可以遍历任何实现了 Iterable 接口的对象,包括范围(range)、数组、集合等。

3.1 遍历数值范围

Kotlin 中的 range 表达式非常强大,例如:

for (i in 1..5) {
    println(i) // 输出 1 到 5
}

for (i in 1 until 5) {
    println(i) // 输出 1 到 4,不包含 5
}

for (i in 10 downTo 1 step 2) {
    println(i) // 输出 10, 8, 6, 4, 2
}

🔗 相关阅读:Kotlin Ranges

3.2 遍历数组

声明一个元音字母数组:

val vowels = arrayOf('a', 'e', 'i', 'o', 'u')

遍历元素:

for (vowel in vowels) {
    println(vowel)
}

遍历索引:

for (index in vowels.indices) {
    println(vowels[index])
}

更优雅的方式是使用 withIndex() 同时获取索引和值:

for ((index, vowel) in vowels.withIndex()) {
    println("索引 $index 处的元音是:$vowel")
}

📌 原理说明:withIndex() 返回的是 IndexedValue 对象,通过解构声明(destructuring declaration)自动提取 component1()(index)和 component2()(value)。

🔗 深入理解:Kotlin 解构声明

3.3 遍历 List

List 是有序可重复的集合,遍历方式与数组类似:

val names = listOf("Alice", "Bob", "Charlie")
for (name in names) {
    println(name)
}

也可以通过索引遍历:

for (i in names.indices) {
    println("$i: ${names[i]}")
}

🔗 参考文档:Kotlin Lists - Loops按索引遍历集合

3.4 遍历 Map

Map 存储键值对,遍历方式多样:

val capitalCityByCountry = mapOf(
    "Netherlands" to "Amsterdam",
    "Germany" to "Berlin", 
    "USA" to "Washington, D.C."
)

遍历每个 entry:

for (entry in capitalCityByCountry) {
    println("首都 ${entry.value} 属于国家 ${entry.key}")
}

仅遍历 key 或 value:

// 遍历 key
for (country in capitalCityByCountry.keys) {
    println(country)
}

// 遍历 value
for (capitalCity in capitalCityByCountry.values) {
    println(capitalCity)
}

推荐使用解构声明直接获取 key 和 value:

for ((country, capitalCity) in capitalCityByCountry) {
    println("国家 $country 的首都是 $capitalCity")
}

这种方式代码更清晰,也更符合 Kotlin 的函数式风格。

3.5 函数式遍历:forEach

除了传统的 for 循环,Kotlin 更推荐使用函数式风格的 forEach

names.forEach { name ->
    println(name)
}

// 带索引的 forEach
names.forEachIndexed { index, name ->
    println("$index: $name")
}

✅ 优势:链式调用友好,配合 filtermap 等操作更简洁。

❌ 缺点:在 lambda 中使用 breakcontinue 会受限(需要标签),性能略低于原生 for(但通常可忽略)。

🔗 进阶用法:Nested forEach in Kotlin

4. while 循环

while 循环在布尔表达式为 true 时持续执行:

var counter = 0
while (counter < 5) {
    println("while 循环计数器: ${counter++}")
}

输出:0 到 4。

⚠️ 关键特性:先判断条件,再执行循环体。这意味着如果初始条件为 false,循环体一次都不会执行:

while (false) {
    println("这行永远不会输出")
}

无限循环写法:

while (true) {
    println("我是一个无限循环")
}

实际开发中应避免死循环,除非配合外部中断逻辑(如线程控制)。

5. do..while 循环

do..whilewhile 的最大区别在于:先执行循环体,再判断条件

语法:

do {
    // 执行语句
} while (布尔表达式)

示例:

var counter = 0
do {
    println("do..while 计数器: ${counter++}")
} while (counter < 5)

输出同样是 0 到 4。

✅ 核心优势:至少执行一次。即使条件一开始就不满足:

do {
    println("这行一定会输出一次")
} while (false)

这个特性在需要“至少尝试一次”的场景下非常有用,比如用户输入验证。

6. return、break 与 continue

Kotlin 提供了三种结构化跳转表达式:

  • return:退出当前函数
  • break:跳出当前循环
  • continue:跳过本次迭代,进入下一次

示例:

for (i in 1..10) {
    if (i == 5) break       // 结束循环
    if (i % 2 == 0) continue // 跳过偶数
    println(i)              // 输出 1, 3
}

⚠️ 踩坑提醒:在一个循环中频繁使用多个 breakcontinue 是典型的 code smell(代码异味),会导致逻辑混乱,建议重构为更清晰的结构或提取成函数。

🔗 详细规则:Kotlin return, break, continue

7. 多变量循环

有时我们需要同时遍历多个序列,Kotlin 提供了优雅的解决方案。

7.1 使用 zip 操作符

假设有两个队伍进行配对比赛:

val teamA = listOf("A1", "A2", "A3")
val teamB = listOf("B1", "B2")

使用 zip 将两个列表按顺序配对,较短的列表决定最终长度:

fun showMatches(team1: List<String>, team2: List<String>) {
    for ((player1, player2) in team1 zip team2) {
        println("$player1 vs $player2")
    }
}

调用 showMatches(teamA, teamB) 输出:

A1 vs B1
A2 vs B2

⚠️ 注意:teamAA3 被自动忽略。

另一种思路:先合并再遍历:

fun showMatchLabels(team1: List<String>, team2: List<String>) {
    val matches = team1.zip(team2) { p1, p2 -> "$p1 vs $p2" }
    for (match in matches) {
        println(match)
    }
}

🔗 API 文档:Kotlin zip 函数

7.2 生成乘法表

结合 range 和 zip 生成指定区间的乘法表:

fun printMultiplicationTable(factor: Int, start: Int, end: Int) {
    val multipliers = start..end
    val results = (factor * start)..(factor * end) step factor
    for ((multiplier, result) in multipliers zip results) {
        println("$factor x $multiplier = $result")
    }
}

测试:

printMultiplicationTable(27, 3, 7)

输出:

27 x 3 = 81
27 x 4 = 108
27 x 5 = 135
27 x 6 = 162
27 x 7 = 189

📌 技巧:results 是一个 progression(步进序列),步长为 factor,这是实现的关键。

8. 总结

本文全面梳理了 Kotlin 的循环机制:

  • repeat:固定次数执行,简洁明了
  • for:最常用,支持 range、数组、集合及解构
  • while:先判后执,可能一次都不执行
  • do..while:先执后判,至少执行一次
  • 多变量循环:善用 zip 实现优雅配对
  • 跳转控制:合理使用 break / continue,避免过度嵌套

作为高级开发者,不仅要掌握语法,更要理解其适用场景和潜在陷阱。例如,在性能敏感的循环中优先使用原生 for 而非 forEach;在需要解耦逻辑时考虑函数式风格。

✅ 最佳实践:优先选择表达力强且不易出错的语法(如 for + in),避免过度使用跳转语句。

所有示例代码已整理至 GitHub:

https://github.com/baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-3


原始标题:Kotlin Loops