大數據學習(二十一)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

記錄一下,怕以後自己忘記
大家共勉~

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