大数据学习(二十一)spark高级算子

简介

这次主要分享一下spark RDD的常用的算子。
然后利用这些算子进行一些实战的操作。

高级算子

  1. mapPartitionsWithIndex

源码:

def mapPartitionsWithIndex[U: ClassTag](
	f:(Int, Iterator[T]) => Iterator[U],

第一个参数:分区号
第二个参数:分区中的元素

demo1:

val RDD1 = sc.parallelize(List(1,2,3,4,5,6,7),2)
//然后我们创建一个函数来返回RDD中的分区和相应的元素
def func1(index : Int,iter :  Iterator[int]):Interator[String]={
	iter.toList.map( x => "(PartID:"+index+",value:"+x+")").iterator
}

//然后我们调用
RDD1.mapPartitionsWithIndex(func1).collect

这样就得到了每个值的对应分区。

  1. aggregate

作用:先对局部做聚合操作,然后再对全局聚合操作。

源码:

def aggregate[U:ClassTag](zeroValue:U)(seqOp:(U,T) => U, combOp: (U, U) => U):
    .....

我们直接看圆括号中的参数:
分别是 初始值 局部操作 全局操作。

下面我们通过例子来尝试一下:
目的是找到每一个分区的最大值进行求和。

val RDD = sc.parallelize(List(1,2,3,4,5,6),2)
//我们可以通过上一个我们写的demo来查看一下分区的情况,这里不再展示了。
RDD.aggregate(0)(math.max(_,_),_+_)

这样我们就可以得到每一个partition中最大值的和了。
那么我们来分析一下。

一共输入了三个参数,

  • 0:意味着初始值是0
  • math.max(_,_) :
    这是一个局部操作的函数,也就是再partition之中的操作,就是求每一个partition中的最大值。

当得到了每个分区的最大值了以后,再进入全局的处理阶段,也就是_+_这个匿名函数。

  • _+_
    这个逻辑就更简单了,就是对每个值求和。

这不就很清楚的完成了我们的操作了吗。yep

注:
这里比较需要注意的是初始值,这是什么意思呢:
当我们设置初始值为n的时候,就会在每个partition中
增加一个n元素,然后执行上述逻辑,并且在最终的全局操作阶段还会增加一个n元素。
那么当我们输入的初始值为100的时候,上述代码的结果会变为300。

  1. aggregrateByKey

这里我们直接举例子

比如我们现在有一个List,分成了两个partition
partition1:(tom, 1000)
(braylon, 2000)
(sam, 3000)
(sam, 2000)
partition1:(tom, 500)
(braylon, 500)
(sam, 500)
这里表示的是每个人的名字和工资。
现在我们要将每个分区中的工资最多的人的工资求和

RDD.aggregateByKey(0)(math.max(_,_),_+_).collect
  • 过程分析

首先,对于每个Partition进行max操作,也就是对于相同的key的数组,他只选择最大的,比如partition1中两个sam只选择3000的sam。

然后, 对于每个paritton中得到的map,对相同key的map将value相加。

最终得到:
(tom,1500)(braylon,2500) (sam,3500)

  1. coalesce 和 repartition

都是用来将RDD中的分区进行重分区。

但是他们还是有区别的:
对coalesce: 默认不会进行shuffle

但是对于repartition:会进行shuffle,也就是会将数据真正通过网络进行重新分区。

但是其实coalesce是可以设置为shuffle的

Rdd.coalesce(8,true)=Rdd.repartition(8)

同理如果我们输入
Rdd.coalesce(3)的话得到的Rdd.length()还是原来的值。

常用操作

//按key进行聚合
val rdd1 = rdd.reduceByKey(_ + _)
rdd1.collect
//按value的降序排序
val rdd1 = rdd.map(t => (t._2, t._1)).sortByKey(false).map(t => (t._2, t._1))
rdd1.collect
//通过并行化生成rdd
val rdd1 = sc.parallelize(List(5, 6, 4, 7, 3, 8, 2, 9, 1, 10))
//对rdd1里的每一个元素乘2然后排序
val rdd2 = rdd1.map(_ * 2).sortBy(x => x, true)
//过滤出大于等于十的元素
val rdd3 = rdd2.filter(_ >= 10)
//将元素以数组的方式在客户端显示
rdd3.collect
val rdd1 = sc.parallelize(List(2, 4, 6, 8))
val rdd2 = sc.parallelize(List(1, 2, 3, 4))
//求并集
val rdd3 = rdd1.union(rdd2)
//求交集
val rdd4 = rdd1.intersection(rdd2)
//去重
rdd3.distinct.collect
rdd4.collect

记录一下,怕以后自己忘记
大家共勉~

发布了49 篇原创文章 · 获赞 52 · 访问量 8510

猜你喜欢

转载自blog.csdn.net/qq_40742298/article/details/104363329