5Scala for the Impatient(第2版)

集合

集合框架

不可变集合可变集合Stream并行集合

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第5章:集合

一、导读

1.1 本章学习目标

第5章讲解 Scala 的集合框架:不可变集合、可变集合、Stream、并行集合。

本章核心学习目标:

  • 掌握不可变集合:List、Vector、Map、Set
  • 理解可变集合:mutable 包
  • 掌握集合操作:map、filter、flatMap、fold
  • 了解并行集合

1.2 为什么本章如此重要

Scala 的集合库是其最强大的特性之一。不可变集合和函数式操作是 Scala 代码的核心。

1.3 核心问题引导

不可变集合如何高效地"修改"?

Stream(LazyList)如何实现惰性求值?

并行集合如何加速计算?


二、核心概念详解

5.1 不可变集合

scala
import scala.collection.immutable._

// List: 链表,头部操作 O(1)
val list = List(1, 2, 3)
val newList = 0 :: list  // List(0, 1, 2, 3)

// Vector: 随机访问 O(log32 n)
val vec = Vector(1, 2, 3, 4, 5)
val newVec = vec.updated(2, 99)  // Vector(1, 2, 99, 4, 5)

// Map
val map = Map("a" -> 1, "b" -> 2)
val newMap = map + ("c" -> 3)  // Map(a -> 1, b -> 2, c -> 3)
val updated = map.updated("a", 10)  // Map(a -> 10, b -> 2)

// Set
val set = Set(1, 2, 3)
val newSet = set + 4  // Set(1, 2, 3, 4)

5.2 集合操作

scala
val nums = List(1, 2, 3, 4, 5)

// 转换
nums.map(_ * 2)           // List(2, 4, 6, 8, 10)
nums.filter(_ % 2 == 0)   // List(2, 4)
nums.flatMap(n => List(n, n * 10))  // List(1, 10, 2, 20, ...)

// 归约
nums.sum                  // 15
nums.product              // 120
nums.foldLeft(0)(_ + _)   // 15
nums.reduce(_ max _)      // 5

// 分组
nums.groupBy(_ % 2)       // Map(false -> List(2, 4), true -> List(1, 3, 5))

// 拉链
val names = List("Alice", "Bob")
val ages = List(30, 25)
names.zip(ages)           // List((Alice,30), (Bob,25))

// 分区
nums.partition(_ > 3)     // (List(4, 5), List(1, 2, 3))

5.3 LazyList (Stream)

scala
// 惰性列表: 按需计算
lazy val naturals: LazyList[Int] = 1 #:: naturals.map(_ + 1)

println(naturals.take(10).toList)  // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 斐波那契数列
lazy val fibonacci: LazyList[BigInt] = 
    BigInt(0) #:: BigInt(1) #:: fibonacci.zip(fibonacci.tail).map(p => p._1 + p._2)

println(fibonacci.take(20).toList)

// 惰性过滤
val primes = LazyList.from(2).filter(isPrime)
def isPrime(n: Int): Boolean = !(2 until n).exists(n % _ == 0)

5.4 并行集合

scala
import scala.collection.parallel.CollectionConverters._

// 并行集合
val largeList = (1 to 1000000).toList

// 顺序版本
val sum1 = largeList.map(_ * 2).filter(_ > 500000).sum

// 并行版本
val sum2 = largeList.par.map(_ * 2).filter(_ > 500000).sum

// 注意: 并行集合的操作必须是无副作用的

三、实战案例

3.1 案例一:词频统计

scala
val text = """
Scala is a modern programming language.
Scala combines object-oriented and functional programming.
Scala runs on the JVM.
"""

val wordCount = text
    .toLowerCase
    .split("\\s+")
    .filter(_.nonEmpty)
    .groupBy(identity)
    .view
    .mapValues(_.size)
    .toMap

// 按频率排序
val sorted = wordCount.toList.sortBy(-_._2)
sorted.foreach { case (word, count) =>
    println(f"$word%-15s $count%d")
}

四、本章小结

不可变集合是默认选择,安全且高效

LazyList 实现惰性求值

并行集合加速大规模数据处理


五、思考与练习

不可变 List 的 :: 操作的时间复杂度是多少?

并行集合在什么情况下比顺序集合慢?


5/7集合
0%