1. 概述

在 Kotlin 开发中,经常需要将数组内容转换为字符串,比如用于日志输出、调试信息或接口返回。本文将介绍 四种常见方法,并从代码简洁性、可读性和灵活性角度进行对比。

我们将依次讨论:

contentToString():最简单的内置方法
reduce():函数式风格,灵活拼接
fold():支持初始值的聚合操作
for 循环:传统 imperative 写法

每种方式都有其适用场景,选择时需权衡需求与可维护性。


2. contentToString()

这是最直接的方式,适用于快速查看数组内容,尤其适合调试和日志打印。

该方法底层调用的是 Java 的 Arrays.toString(),返回一个用逗号分隔、并用方括号包裹的字符串。

val stringArray: Array<String> = arrayOf("java", "kotlin", "scala")
assertEquals("[java, kotlin, scala]", stringArray.contentToString())

对于非字符串类型的数组,会自动调用每个元素的 toString() 方法:

val intArray: IntArray = intArrayOf(9, 8, 7, 6)
assertEquals("[9, 8, 7, 6]", intArray.contentToString())

⚠️ 局限性:无法自定义分隔符或去除首尾的 []。若需要,只能后续通过 replace() 处理,略显笨拙。

例如要去掉括号:

intArray.contentToString().removeSurrounding("[", "]") // "9, 8, 7, 6"

✅ 适合:快速调试、不关心格式的场景
❌ 不适合:需要定制输出结构的情况


3. reduce()

当你想完全控制拼接逻辑时,reduce() 是个不错的选择。它允许你指定连接方式,比如使用分号、竖线或其他符号。

val stringArray: Array<String> = arrayOf("java", "kotlin", "scala")

val result = stringArray.reduce { acc, item -> "$acc; $item" }

assertEquals("java; kotlin; scala", result)

⚠️ 注意:reduce() 要求集合非空,否则会抛出 UnsupportedOperationException。空数组调用直接踩坑!

另外,如果数组元素不是字符串类型(如 IntArray),必须先 map 成字符串:

val intArray: IntArray = intArrayOf(9, 8, 7, 6)

val result = intArray
    .map { it.toString() }
    .reduce { acc, item -> "$acc; $item" }

assertEquals("9; 8; 7; 6", result)

✅ 优点:

  • 完全掌控拼接逻辑
  • 可结合 map 实现复杂格式化

❌ 缺点:

  • 空集合不支持
  • 链式调用稍长

4. fold()

fold()reduce() 类似,但更强大:它可以指定初始值,并且允许结果类型与元素类型不同。

这意味着我们可以直接从空字符串开始累积,无需提前 map 转换类型。

不过需要注意:初始值为空字符串时,第一次拼接容易多出分隔符,需手动判断处理。

val intArray: IntArray = intArrayOf(9, 8, 7, 6)

val result = intArray.fold("") { acc, item ->
    if (acc.isEmpty()) "$item" else "$acc; $item"
}

assertEquals("9; 8; 7; 6", result)

✅ 优势:

  • 支持空集合(返回初始值)
  • 不依赖 map,性能略优
  • 更安全,不易因空数组崩溃

📌 小技巧:也可以用 foldIndexed 来判断是否是第一个元素,避免 isEmpty() 判断:

val result = intArray.foldIndexed("") { index, acc, item ->
    if (index == 0) "$item" else "$acc; $item"
}

🔗 延伸阅读:fold 与 reduce 的区别


5. for 循环

最传统的做法:用可变变量 + for 循环逐步拼接。

虽然不够“函数式”,但在某些性能敏感或逻辑复杂的场景下反而更清晰。

val intArray: IntArray = intArrayOf(9, 8, 7, 6)

var result = intArray[0].toString()
for (i in 1..<intArray.size) {
    result += "; ${intArray[i]}"
}

assertEquals("9; 8; 7; 6", result)

⚠️ 踩坑提醒:

  • 数组必须非空,否则 intArray[0] 直接 NPE
  • 字符串频繁 += 拼接效率低(建议用 StringBuilder 优化)

优化版:

val result = buildString {
    for (i in intArray.indices) {
        if (i > 0) append("; ")
        append(intArray[i])
    }
}

✅ 适用场景:

  • 对性能要求高
  • 拼接逻辑复杂(如条件判断、换行等)

❌ 缺点:代码冗长,不够声明式

🔗 参考:Kotlin 中的循环语法


6. 总结

方法 是否支持空数组 是否可定制分隔符 是否需预处理 推荐程度
contentToString() ⭐⭐
reduce() ❌(会崩溃) ✅(需 map) ⭐⭐⭐
fold() ⭐⭐⭐⭐
for loop ❌(需判空) ⭐⭐⭐

📌 最佳实践建议:

  • 日常调试 ➜ 用 contentToString()
  • 函数式偏好 ➜ 优先选 fold()
  • 性能关键路径 ➜ 用 buildString { ... } + 循环
  • 空数组常见场景 ➜ 避免 reduce()

所有示例代码已上传至 GitHub:https://github.com/Baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-collections-5


原始标题:Convert an Array to a String