当前位置: 首页 > ds >正文

spark:map 和 flatMap 的区别(Scala)

场景设定

假设有一个包含句子的 RDD:

scala

val rdd = sc.parallelize(List("Hello World", "Hi Spark"))  

目标是:将每个句子拆分成单词


1. 用 map 的效果

代码示例

scala

val resultMap = rdd.map(sentence => sentence.split(" "))
resultMap.collect()
输出结果

scala

Array[Array[String]] = Array(Array("Hello", "World"), Array("Hi", "Spark"))
发生了什么?
  • map 一对一转换:

    • 输入一个句子 "Hello World" → 输出一个单词数组 Array("Hello", "World")

    • 输入一个句子 "Hi Spark" → 输出一个单词数组 Array("Hi", "Spark")

  • 结果结构嵌套的数组(每个元素还是数组)。


2. 用 flatMap 的效果

代码示例

scala

val resultFlatMap = rdd.flatMap(sentence => sentence.split(" "))
resultFlatMap.collect()
输出结果

scala

Array[String] = Array("Hello", "World", "Hi", "Spark")
发生了什么?
  • flatMap 一对多转换:

    • 输入一个句子 "Hello World" → 拆分成两个单词 "Hello" 和 "World"

    • 输入一个句子 "Hi Spark" → 拆分成两个单词 "Hi" 和 "Spark"

  • 结果结构扁平化的数组(所有单词在一个数组中)。


核心区别总结

操作输入 → 输出关系结果结构适用场景
map1个输入 → 1个输出(类型可变)保持嵌套结构简单转换(如类型转换、数值计算)
flatMap1个输入 → 多个输出(自动展平)扁平化单层结构拆分数据(如分词、展开嵌套结构)

图解对比

原始数据:          List("Hello World", "Hi Spark")  ↓               ↓  
map 处理:      Array("Hello", "World")   Array("Hi", "Spark") → 结果:嵌套数组  |         |            |        |  
flatMap 处理:  "Hello"    "World"     "Hi"     "Spark"      → 结果:扁平数组

什么时候用 map

  • 保留结构:比如将字符串转大写、对数字做运算。

    scala

    val numbers = sc.parallelize(List(1, 2, 3))
    val doubled = numbers.map(_ * 2)  // 输出:List(2, 4, 6)

什么时候用 flatMap

  • 拆分或展开数据:比如将句子拆成单词、展开嵌套集合。

    scala

    val nestedList = sc.parallelize(List(List(1, 2), List(3, 4)))
    val flattened = nestedList.flatMap(identity)  // 输出:List(1, 2, 3, 4)

高级用法

链式调用示例

scala

// 同时使用 map 和 flatMap
val sentences = sc.parallelize(List("Hello World", "Hi Spark"))// 步骤分解:
// 1. 用 map 将句子转大写
// 2. 用 flatMap 拆分单词
val result = sentences.map(_.toUpperCase).flatMap(_.split(" "))result.collect()  // 输出:Array("HELLO", "WORLD", "HI", "SPARK")

一句总结

map 是变形,flatMap 是拆开压平!
需要保持结构用 map,需要展开数据用 flatMap

http://www.xdnf.cn/news/5542.html

相关文章:

  • CentOS7离线安装Mysql8
  • 分治算法
  • K8S cgroups详解
  • 【Bluedroid】蓝牙HID DEVICE断开连接流程源码分析
  • 【android bluetooth 框架分析 02】【Module详解 5】【HciLayer 模块介绍】
  • Python3安装HTMLTestRunner
  • 企业内训|智能调控系统算法与优化——某汽车厂商
  • 如何反向绘制出 .NET程序 异步方法调用栈
  • 设计模式学习整理
  • 自然语言处理NLP中的连续词袋(Continuous bag of words,CBOW)方法、优势、作用和程序举例
  • 多空短线决策+飞云分仓操盘,两个副图指标组合操盘技术,短线更精准有效
  • 华为IP(6)
  • 嵌入式硬件篇---SPI
  • 虚幻引擎5-Unreal Engine笔记之常用核心类的继承关系
  • #微调重排序模型:Reranking从入门到实践
  • 医院药品管理系统(准备工作)
  • 元数据和主数据
  • 从代码学习深度学习 - 转置卷积 PyTorch版
  • Oracle 通过 ROWID 批量更新表
  • QT6 源(93)篇三:阅读与注释共用体类 QVariant 及其源代码,本类支持比较运算符 ==、!=。
  • Docker Compose 的历史和发展
  • Python实用工具:pdf转doc
  • flutter 项目工程文件夹组织结构
  • 新手在使用宝塔Linux部署前后端分离项目时可能会出现的问题以及解决方案
  • Linux-TCP套接字编程简易实践:实现EchoServer与远程命令执行及自定义协议(反)序列化
  • 【JavaWeb+后端常用部件】
  • Day 5:Warp高级定制与自动化
  • 足式机器人的全身模型预测控制
  • 常用设计模式
  • 一种混沌驱动的后门攻击检测指标