章节摘要:集合库是 Scala 日常使用率最高的部分,也是第三章函数式技巧的完整演练场。本章从集合类型层级讲起,遍历不可变集合族与可变集合,最后给出"选哪个"的决策依据。读完你能写出既正确又贴合数据规模的集合代码。
金句:选集合先问两个问题——按什么方式访问、要不要可变;其余差异都是这两个问题的推论。
4.1 给地图,4.2 深入默认阵营(不可变),4.3 讲例外情形(可变)与组合子的性能选型——先立规矩再讲例外,顺序本身就是选型逻辑。
[层级地图] -> [不可变主力] -> [可变例外 + 组合子性能] | 第五章:给集合装上类型参数,登上主峰
前置:第三章 map/flatMap 与模式匹配。延伸:5.1 的型变就是从 List 的类型参数讲起的;6.3 会补并发集合。
延续前两章的温度工具,本章让它们处理真实规模的数据——把一年的逐小时读数做成可分析的集合:
case class Row(day: Int, hour: Int, celsius: Double) val rows: List[Row] = loadYear() // 8760 行 val dailyAvg = rows.groupMapReduce(_.day)(_.celsius)( (a, b) => a + b) // 按天求和,再除以小时数得日均 val hot = rows.filter(_.celsius > 35).groupBy(_.day).keySet val top3 = rows.groupBy(_.day) .view.mapValues(rs => rs.map(_.celsius).sum / rs.size) .toList.sortBy(-_._2).take(3) // 最热三天
这条管线用到了本章全部主角:group 前缀家族一次完成分组映射聚合、view 挂在 mapValues 上省一次复制、sortBy 负号做降序。换到 Vector 或再换到 Iterator 流式读取,操作代码几乎不动——这正是集合框架统一接口的兑现时刻。
| 场景 | 首选 | 理由 |
|---|---|---|
| 头部增删频繁 | List | O(1) 结构共享 |
| 随机读写均衡 | Vector | 分块树近似 O(log n) |
| 去重判断 | Set | 哈希成员检查 O(1) |
| 键值映射 | Map | 同上 |
| 超大数据一遍过 | Iterator / view | 惰性,不落地中间结果 |
| 补充一条选型纪律:任何跨方法边界传递的集合,签名上优先写接口而非实现——用 Seq[Row] 而不是 List[Row],给调用方留实现的自由,也给未来替换实现留门。这一习惯到第八章定义库 API 时会再次被强调。 |