Scala Collection
在 Scala 中,集合(Collections)是用于存储和操作一组数据的核心数据结构。Scala 的集合体系非常强大,结合了面向对象和函数式编程的特点,提供了丰富的可变和不可变集合类型,支持高效的遍历、转换和聚合操作。以下是对 Scala 集合的中文讲解,内容简洁清晰,涵盖分类、常用集合、操作方法及注意事项,适合初学者理解。
1. 集合概述
- 定义:集合是存储一组相同或不同类型元素的容器,如列表、数组、集合、映射等。
- 特点:
- 可变 vs 不可变:
- 不可变集合(默认,
scala.collection.immutable
):元素和结构不可修改,操作返回新集合。 - 可变集合(
scala.collection.mutable
):允许修改元素或结构。
- 不可变集合(默认,
- 类型安全:集合元素类型由泛型指定,支持类型推断。
- 函数式支持:提供
map
,filter
,fold
等函数式方法,鼓励无副作用操作。 - 层次结构:所有集合继承自
scala.collection.Iterable
,分为Seq
,Set
,Map
等。 - 用途:数据存储、处理、转换,广泛用于算法、数据分析(如 Spark)等。
2. 集合分类
Scala 的集合体系分为不可变和可变两类,主要类型如下:
分类 | 描述 | 不可变示例 | 可变示例 |
---|---|---|---|
Seq | 有序序列,元素可重复 | List , Vector , Range | ArrayBuffer , ListBuffer |
Set | 无序集合,元素不重复 | Set (默认 HashSet) | mutable.Set , mutable.HashSet |
Map | 键值对集合,键不重复 | Map (默认 HashMap) | mutable.Map , mutable.HashMap |
3. 常用集合类型及用法
1. List(列表)
- 特点:不可变、线性存储、顺序访问,适合递归操作。
- 定义:
val list = List(1, 2, 3)
val list2 = 4 :: list // 添加元素,生成新列表: List(4, 1, 2, 3)
- 操作:
println(list.head) // 输出: 1
println(list.tail) // 输出: List(2, 3)
println(list :+ 4) // 追加: List(1, 2, 3, 4)
println(0 +: list) // 前置: List(0, 1, 2, 3)
2. Array(数组)
- 特点:可变、固定长度、索引访问(详见前文数组讲解)。
- 定义:
val arr = Array(1, 2, 3)
arr(0) = 10 // 修改
println(arr.mkString(", ")) // 输出: 10, 2, 3
3. Vector
- 特点:不可变、随机访问效率高,适合大数据量。
- 定义:
val vec = Vector(1, 2, 3)
println(vec(1)) // 输出: 2
println(vec :+ 4) // 输出: Vector(1, 2, 3, 4)
4. Set(集合)
- 特点:无序、元素不重复,适合去重或快速查找。
- 定义:
val set = Set(1, 2, 2, 3) // 输出: Set(1, 2, 3)
println(set.contains(2)) // 输出: true
println(set + 4) // 输出: Set(1, 2, 3, 4)
5. Map(映射)
- 特点:键值对存储,键唯一,适合快速查找。
- 定义:
val map = Map("Alice" -> 90, "Bob" -> 85)
println(map("Alice")) // 输出: 90
println(map + ("Charlie" -> 95)) // 输出: Map(Alice -> 90, Bob -> 85, Charlie -> 95)
6. ArrayBuffer(可变数组缓冲)
- 特点:可变、动态长度,适合频繁追加/删除。
- 定义:
import scala.collection.mutable.ArrayBuffer
val buffer = ArrayBuffer(1, 2, 3)
buffer += 4 // 追加
buffer(0) = 10 // 修改
println(buffer) // 输出: ArrayBuffer(10, 2, 3, 4)
4. 常用集合操作
Scala 集合支持丰富的函数式操作,简化数据处理:
1. 遍历
foreach
:对每个元素执行操作,无返回值。
List(1, 2, 3).foreach(println) // 输出: 1, 2, 3
2. 转换
map
:转换每个元素,返回新集合。
val doubled = List(1, 2, 3).map(_ * 2)
println(doubled) // 输出: List(2, 4, 6)
flatMap
:转换并展平嵌套集合。
val nested = List(List(1, 2), List(3, 4))
println(nested.flatMap(x => x)) // 输出: List(1, 2, 3, 4)
3. 过滤
filter
:筛选符合条件的元素。
val evens = List(1, 2, 3, 4).filter(_ % 2 == 0)
println(evens) // 输出: List(2, 4)
4. 聚合
reduce
:将集合归约为单个值。
val sum = List(1, 2, 3).reduce(_ + _)
println(sum) // 输出: 6
fold
:带初始值的归约。
val sumWithInitial = List(1, 2, 3).fold(10)(_ + _)
println(sumWithInitial) // 输出: 16(10 + 1 + 2 + 3)
5. 其他操作
- 排序:
sorted
或sortBy
。
val sorted = List(3, 1, 2).sorted
println(sorted) // 输出: List(1, 2, 3)
- 分组:
groupBy
。
val grouped = List(1, 2, 3, 4).groupBy(_ % 2)
println(grouped) // 输出: Map(0 -> List(2, 4), 1 -> List(1, 3))
- 合并:
++
,concat
。
val merged = List(1, 2) ++ List(3, 4)
println(merged) // 输出: List(1, 2, 3, 4)
5. 注意事项
- 不可变优先:Scala 默认导入
scala.collection.immutable
,鼓励使用不可变集合以减少副作用。 - 示例:
List
是不可变的,修改操作返回新列表。 - 可变集合:需显式导入
scala.collection.mutable
,如ArrayBuffer
。 - 性能:
List
:适合头部操作,尾部追加较慢。Vector
:随机访问和更新效率高。ArrayBuffer
:适合动态追加/删除。- 类型推断:
- 混合类型推断为
Any
:scala val mixed = List(1, "Scala") // List[Any]
- 建议显式指定类型以提高可读性。
- 空集合:
List()
、Set()
、Map()
表示空集合。- 检查空:
isEmpty
或nonEmpty
。 - Scala 2 vs Scala 3:
- Scala 3 优化了集合 API,
for
推导式更简洁。 - Scala 3 默认返回类型更一致(如
List
而非Vector
)。 - 与 Java 互操作:Scala 集合可通过
scala.jdk.CollectionConverters
转换为 Java 集合。
6. 实践示例
综合示例,展示常见集合和操作:
import scala.collection.mutable.ArrayBuffer
object CollectionDemo {
def main(args: Array[String]): Unit = {
// List
val list = List(1, 2, 3, 4)
println(s"List: ${list.map(_ * 2)}") // 输出: List(2, 4, 6, 8)
// ArrayBuffer
val buffer = ArrayBuffer(1, 2, 3)
buffer += 4
println(s"ArrayBuffer: $buffer") // 输出: ArrayBuffer(1, 2, 3, 4)
// Set
val set = Set(1, 2, 2, 3)
println(s"Set: ${set + 4}") // 输出: Set(1, 2, 3, 4)
// Map
val map = Map("Alice" -> 90, "Bob" -> 85)
println(s"Map: ${map + ("Charlie" -> 95)}") // 输出: Map(Alice -> 90, Bob -> 85, Charlie -> 95)
// 函数式操作
val numbers = List(1, 2, 3, 4, 5)
val filtered = numbers.filter(_ % 2 == 0)
val sum = numbers.reduce(_ + _)
println(s"Filtered: $filtered, Sum: $sum") // 输出: Filtered: List(2, 4), Sum: 15
}
}
7. 学习建议
- 实践:在 Scala REPL(运行
scala
命令)中测试集合操作,尝试map
,filter
,fold
。 - 函数式思维:优先使用不可变集合,结合函数式方法,减少副作用。
- 性能选择:根据场景选择集合(
List
适合递归,Vector
适合随机访问,ArrayBuffer
适合动态修改)。 - 资源:
- 官方文档:https://www.scala-lang.org/
- Scala Exercises (https://www.scala-exercises.org/)
- 《Programming in Scala》by Martin Odersky
如果需要深入讲解某一集合(如 Map
或 Vector
)或具体操作(如 flatMap
),请告诉我!