map和flatmap的区别(具体实例)

一、写在前面

scala中map和flatmap的区别可以用一句话进行总结,原始RDD假如是10行,经过map操作后依旧是10行,但是flatmap后会>=10行

map是对每一行进行处理,flatmap对每一行进行处理后 如果处理结果的长度是1,那么就和map操作一样;如果处理后是个List或者Array类型,那么就会将这个List或者Array的每个元素变成1行

这篇文章中有两个非常好的例子 https://blog.csdn.net/shenshendeai/article/details/57081673

scala> val rdd = sc.parallelize(List("coffee panda","happy panda","happiest panda party"))
rdd: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[0] at parallelize at :24

scala> rdd.map(x=>x).collect
res0: Array[String] = Array(coffee panda, happy panda, happiest panda party)

scala> rdd.flatMap(x=>x.split(" ")).collect
res1: Array[String] = Array(coffee, panda, happy, panda, happiest, panda, party)

scala> val rdd1 = sc.parallelize(List(1,2,3,3))
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[3] at parallelize at :24

scala> rdd1.map(x=>x+1).collect
res2: Array[Int] = Array(2, 3, 4, 4)

scala> rdd1.flatMap(x=>x.to(3)).collect
res3: Array[Int] = Array(1, 2, 3, 2, 3, 3, 3)

从上面就可以总结出来这个规律,flaMap就是先map,然后再对每个元素flat

网上可以找到很多这样的小例子,但是在实际处理中,多处理的是RDD的键值对,所以下面我举这样一个例子

//定义一个键值对RDD,长度只有1行,已经够说明具体情况
val tmp = List(
("zhangjie",Array(("多余","11.0,25.0",1),
                  ("2511&&&&第二,长度11","第二俄日的长度11",0),
                  ("2522&&&&第二,长度22","第二俄日的长度22",0),
                  ("2533&&&&第二,长度33","第二俄日的长度33",0)))
)
val tmp1 = sc.parallelize(tmp).repartition(1)

// List(imei_expo(0).split(",")(0),imei_expo(0).split(",")(1))是一个List,下面分别对比下map和flatmap的区别
val tmp2 = tmp1.flatMap{t=>
  val imei_expo = t._2.filter(t=> t._3==1).map(_._2) //曝光-下载,根据逗号组成的字符串
  List(imei_expo(0).split(",")(0),imei_expo(0).split(",")(1))
}
//scala> tmp2.take(10).foreach(println)
//11.0
//25.0

val tmp2 = tmp1.map{t=>
  val imei_expo = t._2.filter(t=> t._3==1).map(_._2) //曝光-下载,根据逗号组成的字符串
  List(imei_expo(0).split(",")(0),imei_expo(0).split(",")(1))
}
//  scala> tmp2.count()
//  res63: Long = 1
  
  // days_keywordcuts.map(days_keywordcuts => (days_keywordcuts, imei_expo(0)))的长度是3,所以最后的tmp2的长度也是3
val tmp2 = tmp1.flatMap{t=>
  val imei_expo = t._2.filter(t=> t._3==1).map(_._2) //曝光-下载,根据逗号组成的字符串,长度为1
  val days_keywordcuts = t._2.filter(t=> t._3==0).map(_._1)       //长度为多个
  days_keywordcuts.map(days_keywordcuts => (days_keywordcuts, imei_expo(0)))
}
//scala> tmp2.take(10).foreach(println)
//(2511&&&&第二,长度11,11.0,25.0)
//(2522&&&&第二,长度22,11.0,25.0)
//(2533&&&&第二,长度33,11.0,25.0)
  

 

你可能感兴趣的:(大数据工程)