Scala开发工程师面试宝典 - 第4节

第4章:集合框架与高阶函数

本章聚焦 Scala 核心的集合操作与高阶函数,覆盖 List、Map、Set 的常见用法,以及 map、flatMap、filter、fold 等函数的原理与面试高频考点。掌握这些模式能体现函数式编程思维,是大厂 Scala 岗的必修课。

map vs flatMap 回答框架 定义与区别 返回值类型不同 处理嵌套集合 实际应用场景 代码示例对比 核心:输入类型、输出类型、展平行为
💡 记忆口诀: map 一对一,flatMap 一对零到多个;filter 保留 true,fold 带初始值聚合。

📌 面试问题 1:map 和 flatMap 的区别?

考察点函数式编程理解、类型签名、Option / List 混合用法
回答框架定义 → 返回值差异 → 嵌套集合处理 → 实例 → 总结
示例回答map 对每个元素应用函数,结果仍嵌套;flatMap 会展平一级。例如 List("ab","cd").map(_.toList) 得到 List(List('a','b'), List('c','d')),用 flatMap 则得到 List('a','b','c','d')。
可能追问① flatMap 如何处理 Option? ② 性能上谁优? ③ 能否用 map + flatten 模拟?
避坑提醒✘ 误以为 flatMap 只是 map + flatten(对 Option 也适用但含义不同);✔ 注意传入的函数必须返回可遍历类型(GenTraversableOnce)。

📌 面试问题 2:fold 和 reduce 的区别?

考察点初始值作用、空集合安全处理、结果类型控制
回答框架有无初始值 → 空集合行为 → 结果类型 → 调用方式
示例回答fold(0)(_+_) 对空 List 返回 0;reduce(_+_) 在空 List 抛 UnsupportedOperationException。且 fold 允许结果类型与元素不同(如 fold("")(_+_.toString)),reduce 必须相同。
可能追问① foldLeft / foldRight 区别? ② 时间复杂度? ③ scan 与 fold 关系?
避坑提醒✘ 用 reduce 处理可能为空的集合;✔ 明确 fold 初始值类型与累加器一致(若集合类型为 Int,初始值用 0 而非 0.0)。
面试官追问路径(以 map/flatMap 为例) 初始问题:map vs flatMap 应用场景举例 Option 语义区别 性能与惰性 与 for 推导式关系 追问方向:从“是什么”到“为什么这样设计”到“性能与替代方案”

📌 面试问题 3:如何对 List 进行分组和聚合?

考察点基础算子掌握、函数式聚合思维、多级分组与性能意识
回答框架单级分组 → 值转换 → 多级分组 → 聚合示例
示例回答list.groupBy(_.age) 得到 Map[Int, List[Person]];再 .mapValues(_.size) 得各年龄人数。若需多级分组:list.groupBy(p => (p.age, p.city)),再用 map 统计。
可能追问① groupBy 后如何排序? ② 大量数据时 groupBy 导致的 OOM 风险? ③ 能否用 aggregate 替代?
避坑提醒✘ groupBy 返回 Map 键唯一,若 key 为 case class 需注意 equals/hashCode;✔ 用 view 或 iterator 实现惰性分组以减少内存。

📋 项目案例:电商订单聚合分析系统

项目名称电商订单实时聚合分析平台
业务背景对接电商平台每日百万级订单流,按商家、品类、时间窗口实时聚合成交额、件数等指标,支持运营看板与自助分析。
规模指标日均订单 100 万+,商家 5 万+,品类 2000+,延迟 < 5 秒
技术栈Scala 2.13, Spark Structured Streaming, Kafka, HDFS, Redis 缓存
核心难点
  • 数据倾斜:少数大商家占 40% 订单
  • 内存 OOM:全量 groupBy 后 map 导致内存溢出
  • join 性能:订单表与商品表关联时 shuffle 压力大
面试高频追问
  • 你如何解决数据倾斜? —— 预聚合 + 加盐 + 广播小表
  • 选择 groupBy 还是 reduceByKey? —— RDD 优先 reduceByKey,DataFrame 用 groupBy + agg
  • 如何保证聚合准确性? —— 水位线 + 幂等写入
可迁移回答话术“我在项目中遇到数据倾斜时,首先通过采样识别倾斜 key,然后采用两阶段聚合:第一阶段加随机后缀打散热点,第二阶段去掉后缀合并结果。同时配合广播变量缓存小表,减少 shuffle 数据量。这套方案也适用于其他基于 spark 的聚合场景。”
💡 课程提示: 本章项目案例中,强调“预聚合 + 打散”是面试中体现系统设计能力的关键点,建议结合自己真实项目重构话术。