在 Kotlin 中,遍历(迭代)是操作集合、数组、范围(Range)等数据结构的常见需求。Kotlin 提供了多种遍历方式,语法简洁且功能强大。以下是不同场景下的遍历方法总结,附代码示例:
一、遍历集合(List/Set)
Kotlin 的 List
和 Set
是最常用的集合类型,遍历方式包括传统 for
循环、forEach
高阶函数、forEachIndexed
(带索引)等。
1. 基础 for
循环(直接遍历元素)
Kotlin 的 for
循环可直接遍历集合的元素(无需通过索引),语法简洁:
val fruits = listOf("Apple", "Banana", "Cherry", "Date")
// 遍历所有元素
for (fruit in fruits) {
println(fruit) // 输出:Apple, Banana, Cherry, Date
}
2. forEach
高阶函数(函数式风格)
通过集合的扩展函数 forEach
,可以更函数式地遍历元素。适用于需要对每个元素执行操作的场景:
fruits.forEach { fruit ->
println(fruit) // 输出同上
}
// 简化写法(使用 it 代替参数名)
fruits.forEach { println(it) }
3. forEachIndexed
(带索引遍历)
若需要同时获取元素的索引 和值 ,可以使用 forEachIndexed
:
fruits.forEachIndexed { index, fruit ->
println("索引 $index: $fruit")
// 输出:索引 0: Apple,索引 1: Banana,...
}
4. 通过索引遍历(传统方式)
通过 indices
获取集合的索引范围(0..size-1
),再通过索引访问元素:
for (index in fruits.indices) {
val fruit = fruits[index]
println("索引 $index: $fruit") // 输出同上
}
二、遍历 Map(键值对)
Map
存储键值对(Key-Value),遍历需同时处理键和值。Kotlin 提供了多种遍历方式:
1. 遍历 entries
(键值对)
通过 map.entries
获取所有键值对(类型为 Set<Map.Entry<K, V>>
),直接遍历每个 Entry
:
val userMap = mapOf(
"name" to "Alice",
"age" to 25,
"city" to "Beijing"
)
// 遍历键值对(Entry)
for ((key, value) in userMap) {
println("$key: $value")
// 输出:name: Alice,age: 25,city: Beijing
}
// 或使用 forEach
userMap.forEach { (key, value) ->
println("$key: $value")
}
2. 单独遍历键(Keys)或值(Values)
通过 map.keys
遍历所有键,或通过 map.values
遍历所有值:
// 遍历所有键
for (key in userMap.keys) {
println("Key: $key") // 输出:name,age,city
}
// 遍历所有值
userMap.values.forEach { value ->
println("Value: $value") // 输出:Alice,25,Beijing
}
三、遍历数组(Array)
Kotlin 的数组(如 IntArray
、StringArray
)与集合的遍历方式类似,但需注意基本类型数组(如 IntArray
)的优化。
1. 对象数组(Array<T>
)
普通对象数组的遍历方式与集合完全一致:
val stringArray = arrayOf("A", "B", "C")
// for 循环
for (str in stringArray) {
println(str)
}
// forEach
stringArray.forEach { println(it) }
2. 基本类型数组(如 IntArray
)
Kotlin 对基本类型数组(IntArray
、BooleanArray
等)做了优化,避免装箱开销。遍历方式与对象数组类似:
val intArray = intArrayOf(1, 2, 3, 4)
// for 循环
for (num in intArray) {
println(num) // 输出:1, 2, 3, 4
}
// forEach(优化版,无装箱)
intArray.forEach { println(it) }
// 带索引遍历
intArray.forEachIndexed { index, num ->
println("索引 $index: $num")
}
四、遍历范围(Range)
Kotlin 的范围(如 1..10
表示闭区间 [1,10]
)支持高效遍历,常用于循环计数。
1. 整数范围(IntRange
)
通过 ..
操作符创建范围,配合 for
循环遍历:
// 遍历 1 到 5(包含 5)
for (i in 1..5) {
println(i) // 输出:1, 2, 3, 4, 5
}
// 倒序遍历(使用 downTo)
for (i in 5 downTo 1) {
println(i) // 输出:5, 4, 3, 2, 1
}
// 带步长遍历(使用 step)
for (i in 1..5 step 2) {
println(i) // 输出:1, 3, 5
}
2. 字符范围(CharRange
)
字符也可以组成范围,按 ASCII 顺序遍历:
// 遍历 A 到 C
for (c in 'A'..'C') {
println(c) // 输出:A, B, C
}
五、遍历迭代器(Iterator)
若需要手动控制遍历过程(如跳过某些元素),可以通过 iterator()
获取迭代器,然后使用 hasNext()
和 next()
遍历:
val numbers = listOf(10, 20, 30, 40)
val iterator = numbers.iterator()
while (iterator.hasNext()) {
val num = iterator.next()
println(num) // 输出:10, 20, 30, 40
}
六、注意事项
-
break
和continue
的限制:- 在传统
for
循环中可以使用break
(终止循环)和continue
(跳过当前迭代); - 在
forEach
高阶函数中不支持break
或continue
(因为本质是函数调用)。若需要提前终止,需改用for
循环或使用takeWhile
等操作符。
示例:提前终止遍历
// 使用 for 循环 + break(推荐) for (fruit in fruits) { if (fruit == "Cherry") break // 遇到 "Cherry" 时终止循环 println(fruit) // 输出:Apple, Banana } // 使用 takeWhile(函数式风格,返回满足条件的子列表) fruits.takeWhile { it != "Cherry" }.forEach { println(it) }
- 在传统
-
不可变集合 vs 可变集合 :
若遍历的是可变集合(如
MutableList
),在遍历过程中修改集合 (添加 / 删除元素)可能导致ConcurrentModificationException
(并发修改异常)。需使用listIterator
或复制集合后遍历。
总结:按场景选择遍历方式
场景 | 推荐方法 | 示例代码 |
---|---|---|
简单遍历集合元素 | for 循环 或 forEach |
for (item in list) 或 list.forEach { ... } |
需要索引和元素 | forEachIndexed |
list.forEachIndexed { index, item -> ... } |
遍历 Map 键值对 | for ((key, value) in map) |
for ((k, v) in map) { ... } |
遍历范围(如 1 到 10) | for (i in 1..10) |
for (i in start..end) { ... } |
需要提前终止或跳过元素 | 传统 for 循环 + break /continue |
for (item in list) { if (...) break } |
通过灵活选择这些遍历方式,可以高效处理 Kotlin 中各种数据结构的遍历需求。