1. 概述
数组是存储和操作元素集合的基础数据结构。正向遍历数组是常见操作,但在某些场景下,我们需要反向遍历——从最后一个元素开始,逐个向前访问。
本文将系统介绍在 Kotlin 中实现数组反向遍历的多种方法,适合有一定 Kotlin 使用经验的开发者参考。✅
2. 问题引入
Kotlin 提供了简洁的语法和丰富的内置函数来处理数组。例如,我们可以通过 for
循环或 forEach { }
轻松完成正向遍历:
val array = arrayOf("a", "b", "c", "d", "e", "f")
如果要反向遍历,期望的访问顺序是:"f" -> "e" -> "d" -> "c" -> "b" -> "a"
。
为验证结果正确性,我们先定义一个预期结果列表:
val reversedList = listOf("f", "e", "d", "c", "b", "a")
接下来,我们逐一探讨实现反向遍历的几种方式。
3. 调用数组的 reversed() 函数
Kotlin 为数组提供了 reversed()
扩展函数,它会返回一个元素顺序颠倒的新列表(注意返回类型是 List<T>
,不是 Array<T>
):
public fun <T> Array<out T>.reversed(): List<T> { ... }
我们可以结合 for
循环使用:
val resultList = mutableListOf<String>()
for (element in array.reversed()) {
resultList += element
}
assertEquals(reversedList, resultList)
✅ 优点:代码最简洁,语义清晰。
⚠️ 注意:reversed()
会创建新列表,对大数组可能有性能开销。如果你只关心遍历过程而不需修改原数组,这是最推荐的方式。
4. 对数组索引范围调用 reversed()
如果需要在遍历过程中使用索引(比如同时访问元素和其位置),可以考虑操作索引本身。
Kotlin 数组有一个 indices
属性,返回一个包含所有有效索引的 IntRange
(如 0..5
)。而 IntRange
也支持 reversed()
:
val resultList = mutableListOf<String>()
for (i in array.indices.reversed()) {
resultList += array[i]
}
assertEquals(reversedList, resultList)
这种方式通过反向遍历索引,再用 array[i]
取值,既实现了反向访问,又保留了索引信息。
✅ 适用场景:需要在循环体中使用索引变量时。
5. 使用 downTo() 函数创建递减区间
Kotlin 提供了 downTo()
函数,用于创建一个递减的整数序列。它返回的是 IntProgression
类型,而非 IntRange
。
区别在于:
IntRange
步长固定为 1(或 -1)IntProgression
支持自定义步长
downTo()
本质上就是创建了一个步长为 -1 的 IntProgression
:
public infix fun Int.downTo(to: Int): IntProgression {
return IntProgression.fromClosedRange(this, to, -1)
}
因此,我们可以这样写:
val resultList = mutableListOf<String>()
for (i in (array.lastIndex downTo 0)) {
resultList += array[i]
}
assertEquals(reversedList, resultList)
⚠️ 注意这里的 (array.lastIndex downTo 0)
实际上是调用 array.lastIndex.downTo(0)
。由于 downTo
是一个 infix
函数,我们可以省略点号和括号,写成更自然的中缀表达式。
✅ 优点:性能高,不生成中间集合,直接控制索引。
❌ 缺点:相比 reversed()
稍显啰嗦,但控制力更强。
6. 总结与选型建议
方法 | 是否需要索引 | 性能 | 推荐程度 |
---|---|---|---|
array.reversed() |
❌ 否 | ⚠️ 中等(生成新列表) | ✅ 首选(无需索引时) |
array.indices.reversed() |
✅ 是 | ✅ 高(仅遍历索引) | ✅ 推荐(需要索引时) |
array.lastIndex downTo 0 |
✅ 是 | ✅ 最高(无额外对象) | ✅ 推荐(追求极致性能) |
📌 总结:
- 如果你只关心元素本身,用
reversed()
最简洁。 - 如果需要索引,优先考虑
indices.reversed()
,语义更清晰。 - 在性能敏感场景,可使用
downTo()
,但注意可读性略有下降。
示例完整代码已托管至 GitHub:https://github.com/Baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-arrays-2
踩坑提醒:别把 reversed()
和 reverse()
搞混了!前者返回新列表,后者通常用于原地反转(如 MutableList.reverse()
)。数组没有原地 reverse()
方法,别白折腾。