Spark 之 map 与 flatMap 的区别

map 函数

它将某个函数应用到集合中的每个元素,并产生一个结果集合。

我们可以这样对列表的元素进行平方:

scala 复制代码
scala> list1
res3: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
 
scala> list1.map(x=>x*x)
res4: List[Int] = List(0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100)

flatten 函数

将嵌套结构扁平化为一个层次的集合

scala 复制代码
scala> List(List(1, 2), List(3, 4)).flatten
res0: List[Int] = List(1, 2, 3, 4)

flatMap 函数

flatMap是map的一种扩展。在flatMap中,我们会传入一个函数,该函数对每个输入都会返回一个集合(而不是一个元素),然后,flatMap把生成的多个集合"拍扁"成为一个集合。

scala 复制代码
scala> val list3 = 10 to 20 toList
list3: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
 
scala> val list2 = 1 to 10 toList
list2: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
 
scala> val list4 = List(list2, list3)
list4: List[List[Int]] = List(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))
 
scala> list4.flatMap(x=>x.map(y=>y*2))
res2: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40)

注:flatMap并不一定用于元素是序列的列表,他只需要应用的函数返回的结果是GenTraversableOnce即可(列表的父类),例如:

scala 复制代码
scala> List(1,2,3,4,5)
res0: List[Int] = List(1, 2, 3, 4, 5)
 
scala> res0.flatMap(x => 1 to x )
res1: List[Int] = List(1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5)

flatMap还可以看作是flatten和map两种的结合

scala 复制代码
scala> val nestedNumbers = List(List(1, 2), List(3, 4))
nestedNumbers: List[List[Int]] = List(List(1, 2), List(3, 4))
 
scala> nestedNumbers.flatMap(x => x.map(_ * 2))
res0: List[Int] = List(2, 4, 6, 8)
 
//等价于
 
scala> nestedNumbers.map((x: List[Int]) => x.map(_ * 2)).flatten
res1: List[Int] = List(2, 4, 6, 8)

由以上代码可以看出,flatMap是map和flatten操作的结合,先进行map操作,然后再进行flatten操作;flatMap还可以去除掉空元素NONE。

map VS flatMap

map函数的用法,顾名思义,将一个函数传入map中,然后利用传入的这个函数,将集合中的每个元素处理,并将处理后的结果返回。而flatMap与map唯一不一样的地方就是传入的函数在处理完后返回值必须是List,其实这也不难理解,既然是flatMap,那除了map以外必然还有flat的操作,所以需要返回值是List才能执行flat这一步。

例子:

scala 复制代码
object collection_t1 {

  def flatMap1(): Unit = {
    val li = List(1,2,3)
    val res = li.flatMap(x => x match {
      case 3 => List('a','b')
      case _ => List(x*2)  //输出需要为 List
    })
    println(res)
  }

  def map1(): Unit = {
    val li = List(1,2,3)
    val res = li.map(x => x match {
      case 3 => List('a','b')
      case _ => x*2 // 输入不需要为 List
    })
    println(res)
  }

  def main(args: Array[String]): Unit = {
    flatMap1()
    map1()
  }
}

输出为:

scala 复制代码
List(2, 4, a, b)
List(2, 4, List(a, b))

特别的例子:

scala 复制代码
scala> val books = List("Hadoop", "Hive", "HDFS")
books: List[String] = List(Hadoop, Hive, HDFS)

scala>  books map (s => s.toList)
res3: List[List[Char]] = List(List(H, a, d, o, o, p), List(H, i, v, e), List(H, D, F, S))

scala>  books flatMap (s => s.toList)
res2: List[Char] = List(H, a, d, o, o, p, H, i, v, e, H, D, F, S)

scala> books.map(s => s.toUpperCase)
res1: List[String] = List(HADOOP, HIVE, HDFS)

// flatMap函数的输出结果必须为List,然后才进行flatten,因此,需要将s.toUpperCase生成的 String
// 转为为List,如 "HADOOP".toList 变为 List[Char] = List(H, A, D, O, O, P),进行了隐式转换
// 在进行 flatten
scala> books.flatMap(s => s.toUpperCase)
res0: List[Char] = List(H, A, D, O, O, P, H, I, V, E, H, D, F, S)
相关推荐
PersistJiao1 小时前
在 Spark RDD 中,sortBy 和 top 算子的各自适用场景
大数据·spark·top·sortby
2301_811274311 小时前
大数据基于Spring Boot的化妆品推荐系统的设计与实现
大数据·spring boot·后端
Yz98761 小时前
hive的存储格式
大数据·数据库·数据仓库·hive·hadoop·数据库开发
青云交1 小时前
大数据新视界 -- 大数据大厂之 Hive 数据导入:多源数据集成的策略与实战(上)(3/ 30)
大数据·数据清洗·电商数据·数据整合·hive 数据导入·多源数据·影视娱乐数据
lzhlizihang1 小时前
python如何使用spark操作hive
hive·python·spark
武子康1 小时前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
时差9532 小时前
Flink Standalone集群模式安装部署
大数据·分布式·flink·部署
锵锵锵锵~蒋2 小时前
实时数据开发 | 怎么通俗理解Flink容错机制,提到的checkpoint、barrier、Savepoint、sink都是什么
大数据·数据仓库·flink·实时数据开发
二进制_博客2 小时前
Flink学习连载文章4-flink中的各种转换操作
大数据·学习·flink