1. 概述

在本教程中,我们将介绍如何将一组元素(特别是字符串集合)拼接成一个单独的 String。这是日常开发中非常常见的操作。

2. 字符串集合的拼接方式

作为开发者,我们经常需要处理各种集合,比如 ListArraySet。虽然这些类型不同,但我们经常需要将它们中的所有元素合并为一个字符串。例如,我们可能有一个段落列表,希望将它们合并成完整的文本,并使用换行符 \n 进行连接。

每种编程语言都有自己的解决方案。有些语言通过标准库函数来实现,有些依赖第三方库,还有一些则采用基础循环的方式。下面我们来看几种 Scala 中常用的拼接方式。

2.1. 使用 mkString

这是最常用、最地道的方式之一,使用简单,功能强大。我们只需要调用 .mkString 方法即可完成拼接:

scala> List("a","b","c").mkString 
val res1: String = abc

✅ 它还支持自定义分隔符:

scala> List("a","b","c").mkString(",") 
val res2: String = a,b,c 

scala> List("a","b","c").mkString("-") 
val res3: String = a-b-c

⚠️ 这个方法适用于所有实现了 GenTraversableOnce 的集合类型,包括 ListSetArray、甚至 Map

scala> Array("a","b","c").mkString("/")
val res4: String = a/b/c

scala> Set("a","b","c").mkString("/")
val res5: String = a/b/c

scala> Map("a"->"A","b"->"B").mkString(" // ")
val res6: String = a -> A // b -> B

2.2. 使用 fold 方法

Scala 提供了强大的集合遍历方法,其中 fold 系列方法(如 foldLeftfoldRight)尤为常用。虽然这里不深入讨论它们之间的区别,但你可以用它们实现拼接逻辑,只需稍作调整即可。

这两个方法接收两个参数:初始值(表示空状态)和合并函数。合并函数负责将当前累积值与下一个元素合并:

scala> List("a","b","c").fold("") { (accumulator, elem) => accumulator + "" + elem }
val res0: String = abc

⚠️ 虽然这种方式功能强大,允许在合并函数中执行复杂逻辑,但它在处理边界情况时不如 mkString 灵活。例如,使用不当会多出一个前导分隔符:

scala> List("a","b","c").fold("") { (accumulator, elem) => accumulator + "/" + elem }
val res1: String = /a/b/c

✅ 解决办法是判断 accumulator 是否为空,或者最后手动去掉第一个字符。

2.3. 使用 reduce 方法

另一个类似 fold 的方法是 reduce 系列方法,包括 reduceLeftreduceRight、以及带 Option 的版本。与 fold 不同,reduce 没有初始值参数,因为它要求集合非空:

scala> List("a","b","c").reduce { (accumulator, elem) => accumulator + elem }
val res0: String = abc

scala> List("a","b","c").reduce { (accumulator, elem) => accumulator + "/" + elem }
val res1: String = a/b/c

2.4. 使用字符串拼接(循环)

最后,我们也可以使用最原始的方式——循环拼接:

scala> var result = ""
var result: String = ""

scala> for (elem <- List("a","b","c")) {
     | result = result + "/" + elem
     | }

scala> result
val res0: String = /a/b/c

❌ 这种方式在 Scala 中并不推荐,属于“不地道”的写法,除非别无选择,否则应避免使用。

2.5. 拼接自定义对象

到目前为止,我们都是拼接字符串。但如果我们要拼接的是自定义对象,该怎么办?比如我们有一个对象列表,需要将它们的属性拼接成 CSV 格式的字符串。

✅ 最简单的做法是先将对象转换为字符串表示,再进行拼接。例如,使用 case class 时非常方便:

scala> case class Person(firstName: String, lastName: String)
class Person

scala> val p1 = Person("John", "Doe")
val p1: Person = Person(John,Doe)

scala> val p2 = Person("Jane", "Doe")
val p2: Person = Person(Jane,Doe)

scala> List(p1,p2).map(_.toString).mkString(" and ")
val res0: String = Person(John,Doe) and Person(Jane,Doe)

3. 总结

本文介绍了多种在 Scala 中将字符串集合拼接为单个字符串的方法。从最常用的 mkString 到功能强大的 foldreduce,再到最原始的循环方式,每种方法都有其适用场景。

在实际开发中,推荐优先使用 mkString,不仅简洁易读,还具备良好的边界处理能力。对于更复杂的拼接逻辑,可以考虑使用 foldreduce


原始标题:Joining a Collection of Strings in Scala