1. Kotlin 中的 map() 方法
Kotlin 中的 map()
方法是一个强大的函数式编程工具,可用于对数组中的元素进行转换。但 map()
并不会修改原始数组,而是返回一个包含转换后结果的新数组。
例如,我们可以使用 map()
将数组中的每个元素翻倍:
@Test
fun `Should map an array by doubling all numbers`() {
val numbers = arrayOf(1, 2, 3, 4, 5)
val doubledNumbers = numbers.map { it * 2 }
assertContentEquals(listOf(2, 4, 6, 8, 10), doubledNumbers)
}
上面的代码中,map()
方法返回了一个新数组,原始数组 numbers
并未被修改。
如果我们确实想让原始变量指向新的数组,可以像下面这样操作:
@Test
fun `Should reassign the original variable to the new array`() {
var numbers = arrayOf(1, 2, 3, 4, 5)
numbers = numbers.map { it * 2 }.toTypedArray()
assertContentEquals(arrayOf(2, 4, 6, 8, 10), numbers)
}
✅ 这种方式适用于我们希望保留原始变量名,但指向新数组的情况。
2. 原地修改数组
如果我们希望 直接修改原始数组 而不创建新数组,可以考虑写一个扩展函数,实现类似 map()
的功能,但作用在原数组上。
fun <T> Array<T>.mapInPlace(transform: (T) -> T): Array<T> {
for (i in this.indices) {
this[i] = transform(this[i])
}
return this
}
使用示例:
@Test
fun `Should replace array values in the original array`() {
val numbers = arrayOf(1, 2, 3, 4, 5)
numbers.mapInPlace { it * 2 }
assertContentEquals(arrayOf(2, 4, 6, 8, 10), numbers)
}
⚠️ 这种方式虽然性能更好,但会破坏不可变性(immutability),属于副作用操作,需谨慎使用。
3. map() 与 mapInPlace 的优缺点对比
3.1. 使用 map() 的优缺点
✅ 优点:
- 不可变性保障:不会修改原始数组,避免副作用
- 表达清晰:一行代码即可完成转换,语义明确
- 函数式风格:符合函数式编程范式,易于组合和测试
❌ 缺点:
- 内存开销大:每次转换都生成新数组,大数据量下可能影响性能
- 中间集合过多:链式调用时会产生多个中间集合,增加 GC 压力
3.2. 使用 mapInPlace 的优缺点
✅ 优点:
- 性能更优:避免创建新数组,节省内存和 CPU
- 适合特定场景:如处理大型数组时,原地修改更高效
❌ 缺点:
- 破坏不可变性:引入副作用,增加代码复杂度
- 非函数式风格:不符合现代函数式编程理念,难以维护和测试
4. 小结与建议
在 Kotlin 中,map()
是一个安全、简洁、函数式的方法,适合大多数数组转换场景。它不会修改原始数组,而是返回新数组,这有助于我们写出更清晰、更易维护的代码。
而 mapInPlace()
则更适合一些特定的高性能场景,比如:
- 数组非常大,创建新数组代价高
- 确实不需要保留原始数组
- 对性能敏感的底层处理逻辑
⚠️ 踩坑提醒: 除非你有明确的理由,否则应优先使用 map()
,避免因原地修改带来的副作用和潜在 bug。
完整的示例代码可在 GitHub 上找到。