scala集合
Scala 集合:不可变与可变的完美融合
Scala 集合框架是处理数据集合的核心工具,其设计兼顾了不可变性(线程安全、函数式编程友好)和可变性(性能优化、状态修改),提供了丰富的数据结构(序列、集合、映射等)和操作方法。本文将系统解析 Scala 集合的层级结构、核心类型及常用操作,帮助你高效处理各类数据集合。
集合框架概览
Scala 集合分为两大体系:不可变集合(默认)和可变集合,分别位于不同的包中:
不可变集合:
scala.collection.immutable,集合创建后无法修改,所有操作返回新集合。![不可变集合]()
可变集合:
scala.collection.mutable,集合可直接修改,操作效率更高。![可变集合层级关系]()
核心特质与继承关系
所有集合都扩展自 Iterable 特质,主要分为三大类:
- Seq(序列):有序集合(如数组、列表、队列),元素按顺序访问,可通过索引访问。
- Set(集合):无序集合,元素唯一,无重复值。
- Map(映射):键值对集合,键唯一,值可重复。
序列(Seq)
序列是有序集合,支持索引访问,核心类型包括数组(Array)、变长数组(ArrayBuffer)、列表(List)、队列(Queue)等。
定长数组(Array)
与 Java 数组类似,长度固定,初始化后不可修改,支持泛型。
定义方式
// 方式1:指定长度和类型(默认值为0、null等)
val arr1 = new Array[Int](5) // 长度为5的Int数组,默认值0
val arr2 = new Array[String](3) // 长度为3的String数组,默认值null
// 方式2:直接初始化元素(调用apply方法)
val arr3 = Array(1, 2, 3, 4) // Int数组:Array(1, 2, 3, 4)
val arr4 = Array("a", "b", "c") // String数组:Array(a, b, c)
常用操作
val arr = Array(10, 20, 30)
// 访问元素(索引从0开始)
println(arr(0)) // 输出:10
// 修改元素
arr(1) = 200
println(arr(1)) // 输出:200
// 长度
println(arr.length) // 输出:3
// 遍历
for (num <- arr) println(num)
变长数组(ArrayBuffer)
类似 Java 的 ArrayList,长度可动态变化,适合频繁添加 / 删除元素的场景(需导入 scala.collection.mutable.ArrayBuffer)。
定义与操作
import scala.collection.mutable.ArrayBuffer
// 初始化空数组
val buf = ArrayBuffer[Int]()
// 添加元素
buf += 10 // 追加单个元素
buf += (20, 30) // 追加多个元素
buf ++= Array(40, 50) // 追加数组
// 修改元素
buf(0) = 100
// 删除元素
buf.remove(1) // 删除索引1的元素
buf -= 30 // 删除值为30的元素
// 转换为定长数组
val arr = buf.toArray
// 遍历
buf.foreach(println) // 输出:100, 40, 50
列表(List)
不可变序列,元素按链表结构存储,适合头插操作(效率高),尾插操作效率低。
定义与操作
// 初始化列表
val list1 = List(1, 2, 3) // List(1, 2, 3)
val emptyList = Nil // 空列表:List()
// 头部添加元素(:: 操作符,右结合)
val list2 = 0 :: list1 // List(0, 1, 2, 3)
val list3 = 4 :: 5 :: Nil // List(4, 5)
// 尾部添加元素(效率低,需遍历整个列表)
val list4 = list1 :+ 6 // List(1, 2, 3, 6)
// 列表拼接(::: 拼接两个列表)
val list5 = list2 ::: list3 // List(0, 1, 2, 3, 4, 5)
// 访问元素(索引从0开始)
println(list5(2)) // 输出:2
// 常用方法
println(list5.head) // 首元素:0
println(list5.tail) // 除首元素外的子列表:List(1, 2, 3, 4, 5)
println(list5.isEmpty) // 是否为空:false
可变列表(ListBuffer)
可变版本的 List,支持高效的头部和尾部操作(需导入 scala.collection.mutable.ListBuffer)。
定义与操作
import scala.collection.mutable.ListBuffer
val lb = ListBuffer(1, 2, 3)
// 添加元素
lb += 4 // 尾插
lb.+=:(0) // 头插(等价于 0 +: lb)
lb.insert(2, 100) // 在索引2插入100
// 删除元素
lb.remove(3) // 删除索引3的元素
lb -= 4 // 删除值为4的元素
// 遍历
lb.foreach(println) // 输出:0, 1, 100, 3
队列(Queue)
遵循先进先出(FIFO) 原则的有序集合,分为不可变和可变版本(常用可变队列,需导入 scala.collection.mutable.Queue)。
定义与操作
import scala.collection.mutable.Queue
val queue = Queue(1, 2, 3)
// 入队(添加到尾部)
queue.enqueue(4)
queue += 5
// 出队(移除并返回头部元素)
val head = queue.dequeue() // head = 1,队列变为 Queue(2, 3, 4, 5)
// 访问元素(不修改队列)
println(queue.head) // 头部:2
println(queue.last) // 尾部:5
println(queue.tail) // 除头部外的子队列:Queue(3, 4, 5)
元组(Tuple)
元组用于存储不同类型的元素(最多 22 个),是将多个值封装为单一对象的轻量结构。
定义与操作
// 定义元组(元素类型可不同)
val tuple = (1, "scala", 3.14, true) // Tuple4[Int, String, Double, Boolean]
// 访问元素(索引从1开始,使用 _N 语法)
println(tuple._1) // 1
println(tuple._2) // "scala"
// 遍历(通过 productIterator)
tuple.productIterator.foreach(println) // 依次输出:1, scala, 3.14, true
// 模式匹配提取元素
val (a, b, c, d) = tuple
println(s"a=$a, b=$b") // a=1, b=scala
集合(Set)
Set 是无序且元素唯一的集合,分为不可变和可变版本(默认不可变)。
不可变 Set
// 初始化(自动去重)
val set1 = Set(1, 2, 2, 3) // Set(1, 2, 3)
// 添加元素(返回新集合)
val set2 = set1 + 4 // Set(1, 2, 3, 4)
// 删除元素(返回新集合)
val set3 = set2 - 2 // Set(1, 3, 4)
// 集合运算
val set4 = Set(3, 4, 5)
println(set3 & set4) // 交集:Set(3, 4)
println(set3 ++ set4) // 并集:Set(1, 3, 4, 5)
可变 Set
需导入 scala.collection.mutable.Set,支持直接修改集合。
import scala.collection.mutable.Set
val set = Set(1, 2, 3)
// 添加元素
set += 4
set.add(5)
// 删除元素
set -= 2
set.remove(3)
// 遍历
set.foreach(println) // 输出:1, 4, 5(顺序不固定)
映射(Map)
Map 是键值对(key-value) 集合,键唯一,值可重复,分为不可变和可变版本(默认不可变)。
不可变 Map
// 初始化(键值对用 -> 或元组表示)
val map1 = Map("name" -> "Alice", "age" -> 20)
val map2 = Map(("id", 1), ("score", 90))
// 访问值(get 方法返回 Option,避免空指针)
println(map1.get("name")) // Some(Alice)
println(map1.getOrElse("gender", "unknown")) // unknown(键不存在时返回默认值)
// 添加/修改键值对(返回新 Map)
val map3 = map1 + ("age" -> 21) // 修改 age 的值
val map4 = map3 + ("gender" -> "female") // 添加新键值对
// 删除键(返回新 Map)
val map5 = map4 - "score"
可变 Map
需导入 scala.collection.mutable.Map,支持直接修改。
import scala.collection.mutable.Map
val map = Map("name" -> "Bob", "age" -> 25)
// 添加/修改键值对
map("age") = 26 // 修改
map += ("gender" -> "male") // 添加
map.put("id", 2) // 添加
// 删除键
map -= "name"
map.remove("id")
// 遍历
map.foreach { case (k, v) => println(s"$k: $v") }
// 输出:
// age: 26
// gender: male
集合的通用操作
所有 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。
- 使用可变集合的场景:
- 频繁修改集合(如循环中添加元素),性能更优。
- 需要共享状态并修改(如缓存、计数器)。

