day13-spark 高级算子

前言

day12,我们学习了Spark RDD。今天介绍下并演示下Spark 高级算子的Demo。

什么是算子

RDD调用的方法就是算子,说白了,算子就是一个函数,用于RDD数据的转换或计算。

aggregate

aggregate是Spark官方提供的一个高级算子,它能对RDD数据按分区先进行局部聚合,最后进行全局聚合。

scala> var rdd1 = sc.parallelize(List("12","34","567","8901"),2)
rdd1: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[0] at parallelize at <console>:24

scala> def fun1(index:Int,iter:Iterator[String]):Iterator[String]={
     | iter.toList.map(x => "[partId: " + index + ",value:" + x + "]").iterator}
fun1: (index: Int, iter: Iterator[String])Iterator[String]
#可以看到,获取到分区号,一共有2个分区
scala> rdd1.mapPartitionsWithIndex(fun1).collect
res0: Array[String] = Array([partId: 0,value:12], [partId: 0,value:34], [partId: 1,value:567], [partId: 1,value:8901])

scala> 
#求每个分区元素长度的大最值,然后把各个分区的最大值相加
scala> rdd1.aggregate("")((x,y)=>math.max(x.length,y.length).toString,(x,y)=>x+y)
res1: String = 24

scala> 

scala> rdd1.aggregate("")((x,y)=>math.max(x.length,y.length).toString,(x,y)=>x+y)
res2: String = 42

scala> rdd1.aggregate("")((x,y)=>math.max(x.length,y.length).toString,(x,y)=>x+y)
res3: String = 24

上面的运行结果可以看到,结果有时候是24,有时候是42,具体原因分析如下
第一个分区的元素:“12”,“34”
第一次比较:"",“12” ==>长度大的是2,得到的结果是2.toString,也就是"2"
第二次比较:“2”,“34” ==>长度大的是2,得到的结果是2.toString,也就是"2"

第一个分区的元素:“567”,“8901”
第一次比较:"",“567” ==>长度大的是3,得到的结果是3.toString,也就是"3"
第二次比较:“3”,“8901” ==>长度大的是4,得到的结果是4.toString,也就是"4"

最后全局计算的元素:“2”,“4”
如果是第一个分区先计算完成,则全局计算得出的结果是"24"
如果是第二个分区先计算完成,则全局计算得出的结果是"42"

aggregateByKey

aggregateByKey和aggregate的功能差不多,唯一不同的是针对的数据不同。
aggregate是针对集合的。
aggregateByKey是针对key-value类型的。

scala> var rdd1 = sc.parallelize(List(("Tom",20),("Tom",25),("JinRui",2),("JinRui",18),("Liky",30),("Liky",20),("JinRui",10)),2)
rdd1: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[12] at parallelize at <console>:24
scala> def fun2(index:Int,iter:Iterator[(String,Int)]):Iterator[String]={
     | iter.toList.map(x => "[PartId: " + index + ",value: " + x + "]").iterator} 
fun2: (index: Int, iter: Iterator[(String, Int)])Iterator[String]
scala> rdd1.mapPartitionsWithIndex(fun2).collect
res17: Array[String] = Array([PartId: 0,value: (Tom,20)], [PartId: 0,value: (Tom,25)], [PartId: 0,value: (JinRui,2)], [PartId: 1,value: (JinRui,18)], [PartId: 1,value: (Liky,30)], [PartId: 1,value: (Liky,20)], [PartId: 1,value: (JinRui,10)])
#对每个分区求最大值,最后把最大值加起来。
scala> var rdd2 = rdd1.aggregateByKey(0)(math.max(_,_),_+_)
rdd2: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[14] at aggregateByKey at <console>:26
scala> rdd2.collect
res19: Array[(String, Int)] = Array((Tom,25), (JinRui,20), (Liky,30))
scala>

repartition和coalesce

repartition和coalesce的功能都是重分区。
coalesce:进行重分区的时候默认不会进行shuffle。
repartition:进行重分区的时候默认会进行shuffle。

scala> var rdd1 = sc.parallelize(List(1,2,3,4,5,6,7),2)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24

#指定重分区为 3 个分区
scala> var rdd2 = rdd1.repartition(3)
rdd2: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[8] at repartition at <console>:26

#查看重分区前面的分区数
scala> rdd1.partitions.length
res2: Int = 2

scala> rdd2.partitions.length
res1: Int = 3
#使用coalesce进行分区,虽然指定了重分区为3个分区,但是查看分区后的分区数,还是2,因为coalesce默认是不进行shuffle
scala> var rdd3 = rdd1.coalesce(3)
rdd3: org.apache.spark.rdd.RDD[Int] = CoalescedRDD[9] at coalesce at <console>:26

scala> rdd3.partitions.length
res3: Int = 2

#使用coalesce进行重分区时,只有指定为true,才会进行shuffle
scala> var rdd4 = rdd1.coalesce(3,true)
rdd4: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[13] at coalesce at <console>:26

scala> rdd4.partitions.length
res4: Int = 3

scala>

其它

Spark中的算子非常多,这里不一一列举了,有兴趣的朋友可以到Saprk官方查阅。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值