Skip to content

Scala 集合

Scala 提供了丰富、强大且全面的集合库(collections library),区分可变(mutable)集合和不可变(immutable)集合。不可变集合一旦创建后不能更改,在函数式编程中更受欢迎,因为它们在并发环境中提高了可预测性和安全性。

所有集合的基础特质(base trait)是 Iterable[T]。集合大致分类并位于 scala.collection、scala.collection.immutable 和 scala.collection.mutable 等包(package)中。

当你直接使用 List、Map、Set 而没有从 mutable 显式导入时,你会得到其不可变版本。

一个不可变的链表(linked list)。在头部添加/移除元素(使用 :: 运算符)以及进行模式匹配(pattern matching)时效率较高。通过索引进行随机访问(random access)时效率较低。

val numbers: List[Int] = List(1, 2, 3, 4)
val names = List("Alice", "Bob")
val emptyList = List.empty[Double]
val listWithPrepended = 0 :: numbers // 结果: List(0, 1, 2, 3, 4)

一个不可变的索引序列(indexed sequence)。提供高效的随机访问和更新(接近常数时间)。当其性能特性与 List 不同时,通常是不可变序列的良好默认选择。

val numsVec = Vector(10, 20, 30)
val updatedVec = numsVec.updated(1, 25) // 结果: Vector(10, 25, 30) (新的 Vector)
val appendedVec = numsVec :+ 40 // 结果: Vector(10, 20, 30, 40)

一个不可变的键值对(key-value pair)集合。键是唯一的。

val colors = Map("red" -> "#FF0000", "green" -> "#00FF00", "blue" -> "#0000FF")
val maybeGreen = colors.get("green") // 返回 Option[String]: Some("#00FF00")
val maybeYellow = colors.get("yellow") // 返回 Option[String]: None
val addedColor = colors + ("yellow" -> "#FFFF00") // 添加了 yellow 的新 Map
val removedColor = colors - "red" // 去除了 red 的新 Map

一个包含唯一元素的不可变集合。

val primes = Set(2, 3, 5, 7, 11)
val hasFive = primes.contains(5) // true
val addedPrime = primes + 13 // 添加了 13 的新 Set
val removedPrime = primes - 7 // 去除了 7 的新 Set
val unionSet = primes ++ Set(13, 17) // Set(2, 3, 5, 7, 11, 13, 17)

序列(有序集合)的基础特质。List 和 Vector 是其子类型(subtypes)。当你希望接受任何类型的序列时非常有用。

def processSequence(seq: Seq[Int]): Int = seq.sum
processSequence(List(1, 2, 3)) // 6
processSequence(Vector(4, 5, 6)) // 15

位于 scala.collection.mutable 包中。这些集合可以原地修改(modified in place)。当可变性的性能优势大于不可变性的优点时,或者在与需要可变集合的 Java 库交互时使用它们。

import scala.collection.mutable
// 可变 List Buffer(追加效率高)
val listBuffer = mutable.ListBuffer(1, 2)
listBuffer += 3 // 追加 3: ListBuffer(1, 2, 3)
listBuffer.prepend(0) // 前置 0: ListBuffer(0, 1, 2, 3)
val finalImmutableList = listBuffer.toList // 转换回不可变 List
// 可变 HashMap
val mutableMap = mutable.HashMap("a" -> 1)
mutableMap.put("b", 2) // 原地添加/更新
mutableMap("a") = 10 // 原地更新
// 可变 ArrayBuffer(类似 Java 的 ArrayList)
val arrayBuffer = mutable.ArrayBuffer("x", "y")
arrayBuffer += "z"
arrayBuffer(0) = "a"

表示可选值(optional values)。实例可以是 Some[T](包含一个值)或 None(表示不存在)。对于避免 NullPointerException 和安全处理缺失数据至关重要。

val nameOpt: Option[String] = Some("Scala")
val ageOpt: Option[Int] = None
val upperName = nameOpt.map(_.toUpperCase) // Some("SCALA")
val defaultAge = ageOpt.getOrElse(0) // 0

一个不可变、固定大小的容器,可以容纳可能不同类型(type)的元素(element)(例如 Tuple2[Int, String]、Tuple3[String, Double, Boolean])。当函数需要返回多个值时很有用。

val point: (Int, Int) = (10, 20) // Tuple2[Int, Int]
val personData = ("Alice", 30, true) // Tuple3[String, Int, Boolean]
val x = point._1 // 访问第一个元素(索引从 1 开始)
val name = personData._1
val (pName, pAge, pActive) = personData // 解构

本身不是集合,而是按顺序访问集合元素的一种方式。迭代器(Iterator)是有状态的(stateful),通常只能遍历(traverse)一次。

val iterator = List(1, 2, 3).iterator
while (iterator.hasNext) {
println(s"Iterator element: ${iterator.next()}") // 打印迭代器元素
}

Scala 集合提供了大量强大的高阶函数(higher-order function):

操作描述
map转换每个元素,生成一个新集合。
filter选择满足断言(predicate)的元素,生成一个新集合。
foreach对每个元素应用一个过程(procedure,即带副作用side effect的函数)。
flatMap对每个元素应用一个返回集合的函数,然后将结果展平。
find返回第一个满足断言的元素,作为 Option。
exists检查是否至少有一个元素满足断言。
forall检查是否所有元素都满足断言。
foldLeft使用二元运算符(binary operator)从左开始组合元素。
foldRight使用二元运算符(binary operator)从右开始组合元素。
reduceLeft类似于 fold,但使用第一个元素作为初始值。
reduceRight类似于 fold,但使用最后一个元素作为初始值。
groupBy根据分类函数(classifier function)将元素分区到 Map 中。
sorted根据自然顺序(natural ordering)对元素进行排序。
sortBy根据指定顺序(specified ordering)对元素进行排序。
zip将元素与另一个集合组合。
zipWithIndex将元素与其索引(index)组合。

掌握这些操作是编写简洁且富有表现力的 Scala 代码的关键。