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