1.5. 集合框架
Scala 的集合库提供了丰富且功能强大的不可变和可变集合,并内置了大量高阶操作。
1.5.1. 集合层次结构
Iterable
/ \
Seq Map Set
/ \ / \ / \
Indexed Linear Sorted HashMap Sorted HashSet
| | | | | |
Vector List TreeMap ... TreeSet ...
类别 |
不可变 (immutable) |
可变 (mutable) |
|---|---|---|
序列(有序) |
|
|
集合(无序唯一) |
|
|
映射(键值对) |
|
|
重要
默认导入的是不可变集合 (scala.collection.immutable)。
使用可变集合需显式引入 scala.collection.mutable。
1.5.2. 常用序列
1.5.2.1. List(单向链表)
val list = List(1, 2, 3, 4, 5)
val head = list.head // 1(首元素)
val tail = list.tail // List(2, 3, 4, 5)(除首元素外的剩余)
val prepend = 0 :: list // List(0, 1, 2, 3, 4, 5)
val append = list :+ 6 // List(1, 2, 3, 4, 5, 6)
1.5.2.2. Vector(随机访问序列)
val vec = Vector(1, 2, 3, 4, 5)
vec(0) // 1(索引访问,O(log n))
vec.updated(0, 99) // Vector(99, 2, 3, 4, 5)
vec :+ 6 // Vector(1, 2, 3, 4, 5, 6)
小技巧
Vector 在大多数场景下是 List 的更好替代——随机访问更快,追加操作效率也高。
1.5.2.3. Range(数值范围)
1 to 5 // Range(1, 2, 3, 4, 5)
1 until 5 // Range(1, 2, 3, 4)
1 to 10 by 2 // Range(1, 3, 5, 7, 9)
(5 to 1 by -1).toList // List(5, 4, 3, 2, 1)
1.5.3. 集合核心操作
1.5.3.1. 转换操作
val nums = List(1, 2, 3, 4, 5)
// map: 对每个元素应用函数
nums.map(_ * 2) // List(2, 4, 6, 8, 10)
// flatMap: map + 展平
nums.flatMap(x => List(x, x * 10))
// List(1, 10, 2, 20, 3, 30, 4, 40, 5, 50)
// flatten: 展平嵌套集合
List(List(1, 2), List(3, 4)).flatten // List(1, 2, 3, 4)
1.5.3.2. 筛选操作
val nums = List(1, 2, 3, 4, 5, 6)
// filter: 保留满足条件的元素
nums.filter(_ % 2 == 0) // List(2, 4, 6)
// filterNot: 排除满足条件的元素
nums.filterNot(_ % 2 == 0) // List(1, 3, 5)
// take/drop: 取前 N 个 / 丢弃前 N 个
nums.take(3) // List(1, 2, 3)
nums.drop(3) // List(4, 5, 6)
// distinct: 去重
List(1, 1, 2, 2, 3).distinct // List(1, 2, 3)
1.5.3.3. 聚合操作
val nums = List(1, 2, 3, 4, 5)
// reduce: 用二元操作归约
nums.reduce(_ + _) // 15
// fold: 带初始值的归约
nums.fold(0)(_ + _) // 15
nums.foldLeft(0)(_ + _) // 15(从左到右)
nums.foldRight(0)(_ + _) // 15(从右到左)
// 计数与判断
nums.count(_ > 3) // 2
nums.exists(_ > 10) // false
nums.forall(_ > 0) // true
// 最值
nums.max // 5
nums.min // 1
nums.sum // 15
1.5.3.4. 排序操作
val nums = List(3, 1, 4, 1, 5, 9)
nums.sorted // List(1, 1, 3, 4, 5, 9)
nums.sortBy(-_) // List(9, 5, 4, 3, 1, 1)(按降序)
nums.sortWith(_ > _) // List(9, 5, 4, 3, 1, 1)(自定义比较)
1.5.3.5. 分组操作
val people = List("Alice" -> 30, "Bob" -> 25, "Charlie" -> 30)
// groupBy: 按函数分组
people.groupBy(_._2)
// Map(30 -> List((Alice,30), (Charlie,30)), 25 -> List((Bob,25)))
// partition: 按条件分两组
List(1, 2, 3, 4, 5).partition(_ % 2 == 0)
// (List(2, 4), List(1, 3, 5))
1.5.4. Map 操作
val scores = Map("Alice" -> 95, "Bob" -> 87)
scores("Alice") // 95(不存在时抛出异常)
scores.get("Alice") // Some(95)
scores.get("Charlie") // None
scores.getOrElse("Charlie", 0) // 0
// 增删改(不可变 Map 返回新 Map)
scores + ("Charlie" -> 92) // 添加
scores - "Alice" // 删除
scores.updated("Bob", 90) // 更新
// 遍历
for (name, score) <- scores do
println(s"$name: $score")
1.5.5. Set 操作
val set = Set(1, 2, 3, 3, 2) // Set(1, 2, 3)
set + 4 // Set(1, 2, 3, 4)
set - 1 // Set(2, 3)
set.contains(2) // true
// 集合运算
val a = Set(1, 2, 3)
val b = Set(3, 4, 5)
a.union(b) // Set(1, 2, 3, 4, 5)
a.intersect(b) // Set(3)
a.diff(b) // Set(1, 2)
1.5.6. 视图(View)
视图是惰性集合——操作不会立即执行,只在需要时求值:
val large = (1 to 1_000_000).view
.filter(_ % 2 == 0)
.map(_ * 3)
.take(10)
.toList
// 只处理了前若干个元素,而非整个百万级集合
小技巧
视图适合链式操作中的**多个转换步骤**且有提前截断(take)的场景,
能显著减少中间集合的创建开销。