Spark高级算子:mapPartitionsWithIndex,aggregate,aggregateByKey

1:mapPartitionsWithIndex:

对RDD中的每个分区(带有下标)进行操作,通过自己定义的一个函数来处理
       API文档
       def mapPartitionsWithIndex[U](f: (Int, Iterator[T]) => Iterator[U])
       def mapPartitions[U](f: (Iterator[T]) => Iterator[U]
       
       参数:f 是函数参数,接收两个参数:
       (1)Int:代表分区号
       (2)Iterator[T]:分区中的元素
       (3)返回:Iterator[U]:操作完后,返回的结果
       
       举例:将每个分区中的元素包括分区号,直接打印出来
        (1)创建一个RDD
       
      val rdd1 = sc.parallelize(List(1,2,3,4,5,6,7,8,9),2)
             
        (2)创建函数f,对每个分区中的元素进行操作
             将元素与分区号,拼加起来         

              def func1(index:Int,iter:Iterator[Int]):Iterator[String]={
                iter.toList.map(x=>"[PartID:"+index+",value="+x+"]").iterator
              }


        (3)调用
             rdd1.mapPartitionsWithIndex(func1).collect
             
        (4)输出的结果:
            0号分区对应的数据
            [PartID:0,value=1], [PartID:0,value=2], [PartID:0,value=3], [PartID:0,value=4],        
            
            1号分区对应的数据:
            [PartID:1,value=5], [PartID:1,value=6], [PartID:1,value=7], [PartID:1,value=8], [PartID:1,value=9]
       

2:aggregate

聚合操作,类似分组(Group By)
        (1)先对局部进行聚合操作,然后再对全局进行聚合操作
            val rdd2 = sc.parallelize(List(1,2,3,4,5),2)
            
            调用func1获取每个分区的元素
            rdd2.mapPartitionsWithIndex(func1).collect
            
            结果
            [PartID:0,value=1], [PartID:0,value=2], 
            [PartID:1,value=3], [PartID:1,value=4], [PartID:1,value=5]
    
            调用聚合操作
            (1)初始值是0
                  rdd2.aggregate(0)(math.max(_,_),_+_)
                  
            (2)初始值是10
                  rdd2.aggregate(10)(math.max(_,_),_+_)  结果:30
                  
        

注意:这里初始值设置的不一样,结果也会不同,我们可以看到初始值为0时,结果为7;初始值为10,则结果为30。解释一下原因。

首先两个分区中的数据如下:

[PartID:0,value=1], [PartID:0,value=2]

[PartID:1,value=3], [PartID:1,value=4]

在初始化为10的过程中,首先每个分区与10比较,则分区0和分区1最大值都是10 ,累加后再与初始值10求和,最后得到结果30.

因此,比较后分区0最大值为2,分区1最大值为5,累加后再与初始值0求和,结果则为7。


              
    

3:aggregateByKey

类似aggregate操作,区别:操作的是<Key Value>的数据类型
        API说明:PairRDDFunctions.aggregateByKey
        def aggregateByKey[U](zeroValue: U)(seqOp: (U, V) => U, combOp: (U, U) => U)
        
        准备数据:
        val pairRDD = sc.parallelize(List(("cat",2),("cat", 5),("mouse", 4),("cat", 12),("dog", 12),("mouse", 2)), 2)
        
        重写一个func3查看每个分区中的元素
        def func3(index:Int,iter:Iterator[(String,Int)]) = {
            iter.toList.map(x =>"[PartID:"+index+",value="+x+"]").iterator
        }
        
        pairRDD.mapPartitionsWithIndex(func3).collect
        
        结果
        0号分区(0动物园)
        [PartID:0,value=(cat,2)], [PartID:0,value=(cat,5)], [PartID:0,value=(mouse,4)], 
        
        1号分区(1动物园)
        [PartID:1,value=(cat,12)], [PartID:1,value=(dog,12)], [PartID:1,value=(mouse,2)]
        
        操作:
        (1)将每个动物园(分区)中动物数最多的个数进行求和
                pairRDD.aggregateByKey(0)(math.max(_,_),_+_).collect
                结果:
                Array((dog,12), (cat,17), (mouse,6))
                
        (2)将所有的动物求和
                pairRDD.aggregateByKey(0)(_+_,_+_).collect
                结果:
                Array((dog,12), (cat,19), (mouse,6))
                
                也可以使用reduceByKey
                结果:Array((dog,12), (cat,19), (mouse,6))
    

4:coalesce与repartition

都是对RDD进行重分区
 区别:    

(1)coalesce默认,不会进行Shuffle(false)
                    def coalesce(numPartitions: Int, shuffle: Boolean = false   

(2)repartition:将数据真正进行shuffle(在网络上进行重分区)
                
        举例:
            scala> val rdd1 = sc.parallelize(List(1,2,3,4,5,6,7,8,9),2)
            rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[12] at parallelize at <console>:24

            scala> val rdd2 = rdd1.repartition(3)
            rdd2: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[16] at repartition at <console>:26

            scala> rdd2.partitions.length
            res14: Int = 3

            scala> val rdd3 = rdd1.coalesce(3,true)
            rdd3: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[20] at coalesce at <console>:26

            scala> rdd3.partitions.length
            res15: Int = 3

            scala> val rdd4 = rdd1.coalesce(3)
            rdd4: org.apache.spark.rdd.RDD[Int] = CoalescedRDD[21] at coalesce at <console>:26

            scala> rdd4.partitions.length
            res16: Int = 2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章