1. 简介

在实际开发中,经常会遇到需要反转句子中单词顺序的需求。比如将 "hello world" 变成 "world hello"。这类问题虽然基础,但在字符串处理、编码面试或文本解析场景中非常常见。

Kotlin 提供了多种简洁高效的方式来实现这一功能。本文将带你一步步探索几种主流实现方式,并分析其优劣,方便你在不同场景下做出合适选择。


2. 手动编程实现(循环 + StringBuilder)

我们先从最直观的方式入手:手动遍历单词列表,逐个插入到结果字符串的开头。

目标示例:

输入: "this is a complete sentence"
输出: "sentence complete a is this"

核心思路是使用 split(" ") 拆分句子为单词列表,然后通过 StringBuilder 在每次循环时将当前单词插在前面,从而实现逆序拼接。

fun reverseWordsInSentenceCustomMethod(sentence: String): String {
    val words = sentence.split(" ")
    val reversedStringBuilder = StringBuilder()

    for (word in words) {
        reversedStringBuilder.insert(0, "$word ")
    }

    return reversedStringBuilder.toString().trim()
}

优点:逻辑清晰,适合初学者理解
⚠️ 缺点insert(0, ...) 是 O(n) 操作,频繁头插会导致性能下降(整体复杂度接近 O(n²)),不推荐用于长句子

测试用例:

@Test
fun `reverse sentence using programmatic approach`() {
    val sentence = "this is a complete sentence"
    assertEquals("sentence complete a is this", reverseWordsInSentenceCustomMethod(sentence))
}

💡 踩坑提醒:StringBuilder.insert(0, ...) 看似简单,实则暗藏性能陷阱。每次插入都要移动后续所有字符,数据量大时会明显拖慢速度。


3. 使用 reversed() 与 joinToString()

更 Kotlin 风格的做法是利用标准库提供的高阶函数组合操作。

fun reverseSentenceUsingReverseAndJoinToStringMethods(sentence: String): String {
    val words = sentence.split(" ")
    return words.reversed().joinToString(" ")
}

这段代码三步完成:

  1. split(" ") → 分割成单词列表
  2. .reversed() → 返回一个逆序的只读列表(原列表不变)
  3. .joinToString(" ") → 用空格连接成字符串

优点

  • 代码极简,语义清晰
  • 利用了 Kotlin 标准库的函数式特性
  • 性能良好,适合大多数场景

⚠️ 注意:reversed() 返回的是 List<T>,不是原集合类型,但对 String 处理无影响。

测试验证:

@Test
fun `reverse sentence using split and joinToString methods`() {
    val sentence = "this is a complete sentence"
    assertEquals(
        "sentence complete a is this",
        reverseSentenceUsingReverseAndJoinToStringMethods(sentence)
    )
}

✅ 推荐指数:⭐⭐⭐⭐☆
日常开发首选方案,简洁又高效。


4. 使用 fold 方法

如果你喜欢函数式编程风格,fold 是一个很优雅的选择。

fun reverseSentenceUsingFoldMethod(sentence: String): String {
    return sentence.split(" ")
        .fold("") { accumulator, word -> "$word $accumulator" }
        .trim()
}

📌 工作原理:

  • 初始值为空字符串 ""
  • 每次迭代都将当前 word 放在 accumulator 前面
  • 最终自然形成逆序字符串

例如:

初始: ""
第一次: "this " + ""          → "this "
第二次: "is " + "this "       → "is this "
第三次: "a " + "is this "     → "a is this "
...
最终: "sentence complete a is this"

优点:一行搞定,极具函数式美感
⚠️ 注意点

  • 字符串拼接会产生大量中间对象(除非 JVM 优化)
  • 结果末尾有多余空格,需 trim() 清理

测试代码:

@Test
fun `reverse sentence using a fold method`() {
    val sentence = "this is a complete sentence"
    assertEquals("sentence complete a is this", reverseSentenceUsingFoldMethod(sentence))
}

💬 小建议:这种写法很酷,但在团队项目中要谨慎使用,避免新人看不懂。


5. 使用 Stack 数据结构

利用栈(Stack)的 LIFO(后进先出) 特性,也非常适合解决此类问题。

fun reverseWordsInSentenceUsingStack(sentence: String): String {
    val stack = Stack<String>()
    val words = sentence.split(" ")
    for (word in words) {
        stack.push(word)
    }
    val reversedSentence = StringBuilder()
    while (!stack.empty()) {
        reversedSentence.append("${stack.pop()} ")
    }
    return reversedSentence.toString().trim()
}

流程如下:

  1. 分词 → split(" ")
  2. 全部入栈 → push()
  3. 循环出栈拼接 → pop() 直到栈空

优点

  • 逻辑直观,符合“反转”直觉
  • 易于扩展(如支持多分隔符、过滤空字符串等)

缺点

  • 多引入一个中间容器 Stack,内存开销略高
  • java.util.Stack 是线程安全的,带同步锁,轻微性能损耗

测试用例:

@Test
fun `reverse sentence using a stack`() {
    val sentence = "this is a complete sentence"
    assertEquals("sentence complete a is this", reverseWordsInSentenceUsingStack(sentence))
}

⚠️ 替代方案:可用 ArrayDeque 替代 Stack 提升性能(非同步、双端队列)


6. 总结

方法 代码简洁性 性能 推荐场景
reversed() + joinToString() ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐☆ ✅ 日常开发首选
🔁 自定义循环 + StringBuilder ⭐⭐☆ ⭐⭐ ❌ 仅教学用途
🌀 fold 函数式写法 ⭐⭐⭐⭐☆ ⭐⭐⭐ 🟡 函数式偏好者
📦 使用 Stack ⭐⭐⭐ ⭐⭐⭐ 🟡 教学/面试演示

📌 最终建议

  • 生产环境优先使用 words.reversed().joinToString(" ")
  • 面试时可展示多种解法体现功底
  • 注意边界情况:空字符串、多个空格、null 输入等(本文未覆盖,实际需校验)

所有示例代码及单元测试均已上传至 GitHub:

👉 https://github.com/Baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-strings-4

你可以 clone 下来直接运行测试,加深理解。


原始标题:How to Reverse the Order of Words in a Sentence in Kotlin