Scala 集合:不可变与可变的完美融合
Scala 集合框架是处理数据集合的核心工具,其设计兼顾了不可变性(线程安全、函数式编程友好)和可变性(性能优化、状态修改),提供了丰富的数据结构(序列、集合、映射等)和操作方法。本文将系统解析 Scala 集合的层级结构、核心类型及常用操作,帮助你高效处理各类数据集合。
集合框架概览
Scala 集合分为两大体系:不可变集合(默认)和可变集合,分别位于不同的包中:
不可变集合:
scala.collection.immutable,集合创建后无法修改,所有操作返回新集合。![不可变集合]()
可变集合:
scala.collection.mutable,集合可直接修改,操作效率更高。![可变集合层级关系]()
核心特质与继承关系
所有集合都扩展自 Iterable 特质,主要分为三大类:
- Seq(序列):有序集合(如数组、列表、队列),元素按顺序访问,可通过索引访问。
- Set(集合):无序集合,元素唯一,无重复值。
- Map(映射):键值对集合,键唯一,值可重复。
序列(Seq)
序列是有序集合,支持索引访问,核心类型包括数组(Array)、变长数组(ArrayBuffer)、列表(List)、队列(Queue)等。
定长数组(Array)
与 Java 数组类似,长度固定,初始化后不可修改,支持泛型。
定义方式
1 | // 方式1:指定长度和类型(默认值为0、null等) |
常用操作
1 | val arr = Array(10, 20, 30) |
变长数组(ArrayBuffer)
类似 Java 的 ArrayList,长度可动态变化,适合频繁添加 / 删除元素的场景(需导入 scala.collection.mutable.ArrayBuffer)。
定义与操作
1 | import scala.collection.mutable.ArrayBuffer |
列表(List)
不可变序列,元素按链表结构存储,适合头插操作(效率高),尾插操作效率低。
定义与操作
1 | // 初始化列表 |
可变列表(ListBuffer)
可变版本的 List,支持高效的头部和尾部操作(需导入 scala.collection.mutable.ListBuffer)。
定义与操作
1 | import scala.collection.mutable.ListBuffer |
队列(Queue)
遵循先进先出(FIFO) 原则的有序集合,分为不可变和可变版本(常用可变队列,需导入 scala.collection.mutable.Queue)。
定义与操作
1 | import scala.collection.mutable.Queue |
元组(Tuple)
元组用于存储不同类型的元素(最多 22 个),是将多个值封装为单一对象的轻量结构。
定义与操作
1 | // 定义元组(元素类型可不同) |
集合(Set)
Set 是无序且元素唯一的集合,分为不可变和可变版本(默认不可变)。
不可变 Set
1 | // 初始化(自动去重) |
可变 Set
需导入 scala.collection.mutable.Set,支持直接修改集合。
1 | import scala.collection.mutable.Set |
映射(Map)
Map 是键值对(key-value) 集合,键唯一,值可重复,分为不可变和可变版本(默认不可变)。
不可变 Map
1 | // 初始化(键值对用 -> 或元组表示) |
可变 Map
需导入 scala.collection.mutable.Map,支持直接修改。
1 | import scala.collection.mutable.Map |
集合的通用操作
所有 Scala 集合都支持一系列通用方法,简化数据处理:
| 方法 | 功能描述 | 示例(以 List (1,2,3) 为例) |
|---|---|---|
head |
返回首元素 | list.head → 1 |
tail |
返回除首元素外的子集合 | list.tail → List(2, 3) |
isEmpty |
判断是否为空 | list.isEmpty → false |
nonEmpty |
判断是否非空 | list.nonEmpty → true |
size |
返回元素个数 | list.size → 3 |
contains(x) |
判断是否包含元素 x | list.contains(2) → true |
filter(f) |
过滤出满足条件 f 的元素 | list.filter(_ > 1) → List(2, 3) |
map(f) |
对每个元素应用函数 f 并返回新集合 | list.map(_ * 2) → List(2, 4, 6) |
flatMap(f) |
对每个元素应用函数 f(返回集合)并扁平化 | list.flatMap(x => List(x, x)) → List(1,1,2,2,3,3) |
foldLeft(z)(f) |
从左到右折叠,以 z 为初始值应用函数 f | list.foldLeft(0)(_ + _) → 6 |
foreach(f) |
对每个元素执行函数 f(无返回值) | list.foreach(println) → 打印 1,2,3 |
不可变与可变集合的选择
- 优先使用不可变集合:
- 线程安全,适合并发场景。
- 函数式编程风格(无副作用)。
- 避免意外修改导致的 bug。
- 使用可变集合的场景:
- 频繁修改集合(如循环中添加元素),性能更优。
- 需要共享状态并修改(如缓存、计数器)。

