Spark從零開始學 三

瞭解下Spark的函數API


一 . 創建RDD

1.普通數組創建RDD

val a = sc.parallelize(1to9,3)

這個含義是,生成 1 到 9 的9個數字,分成 3 個區來存儲


2.普通文本文件創建RDD

val b = sc.textFile("README.md")

這個是讀取文本文件來存儲到RDD中,一行作爲一條記錄


二 函數

map

map是對RDD中的每個元素都執行一個指定的函數來產生一個新的RDD。 任何原RDD中的元素在新RDD中都有且只有一個元素與之對應。

val rdd = sc.parallelize(1 to 9, 3)
val rdd2 = rdd.map(x => x * 2)
rdd2.foreach(x => print(x + " "))

結果:

2 4 6

8 10 12

14 16 18

上一個map方法表示把原RDD的每一個元素乘以 2 得到新的RDD


mapValues

作用於有KV的RDD,基於原有的RDD,K 不變,V 做對應的計算,得到新的包含原有K和新V的RDD,和map一樣是對每個元素都要執行,也是一對一

val rdd = sc.parallelize(List("DOG", "TIGER", "LION", "CAT"), 2)

val rdd2 = rdd.map(a => (a.length, a)).mapValues("x" + _ + "x")

rdd2.foreach(x => print(x + " "))

這裏初始化一個RDD,2 個分區,第一個map函數得到KV格式的RDD,如(3,DOG),mapValues函數對V計算,那麼新的V就是xDOGx

結果:

(3,xDOGx) (5,xTIGERx)

(4,xLIONx) (3,xCATx)


flatMap

與map類似,也是處理原RDD中的所有元素,生成一個新RDD

區別是原RDD中的一個元素經map處理後只能生成一個元素,而原RDD中的元素經flatMap處理後可生成多個元素來構建新RDD。

舉例:對原RDD中的每個元素x產生y個元素(從x到5,全部的元素)

val rdd = sc.parallelize(1 to 5, 2)

val rdd2 = rdd.flatMap(x => x to 5)

rdd2.foreach(x => print(x + " "))

初始化一個RDD,存有1 2 3 4 5 ,五個元素2個區,flatMap函數表示將每個元素擴展開,該元素到5的所有元素

舉個例子,如果x=2,那麼經過flatMap處理過後返回 2 3 4 5

結果:

1 2 3 4 5 2 3 4 5

3 4 5 4 5 5


flatMapValues

與mapValues相似,每個一元素的V被輸入函數映射爲一系列的值,然後這些值再與原RDD中的K組成一系列新的KV對。

val rdd = sc.parallelize(List((1, 2), (3, 4), (3, 6)))

val rdd2 = rdd.flatMapValues(x => x.to(5))

rdd2.foreach(x => print(x + " "))

初始化一個原RDD,這裏採用默認的一個分區

這裏舉個例子,原RDD要處理KV元素(1,2),經過flatMapValues把V擴展開爲 2 3 4 5,再與原K組成新的KV對 (1,2) (1,3) (1,4) (1,5)

結果:

(1,2) (1,3) (1,4) (1,5) (3,4) (3,5)


reduce

reduce將RDD中元素兩兩傳遞給輸入函數,同時產生一個新的值,新產生的值與RDD中下一個元素(第三個元素)再被傳遞給輸入函數直到最後只有一個值爲止。

val rdd = sc.parallelize(1 to 10)

val rdd2 = rdd.reduce((x, y) => x + y)

println(rdd2)

具體過程,RDD有1 2 3 4 5 6 7 8 9 10個元素, 這裏 reduce((x,y)=>x+y) 等同爲 reduce(_ + _)

1+2=3  3+3=6  6+4=10  10+5=15  15+6=21  21+7=28  28+8=36  36+9=45  45+10=55

結果:

55


reduceByKey

顧名思義,reduceByKey就是對元素爲KV對的RDD中K相同的元素的V進行reduce

因此,K相同的多個元素的值V被reduce爲一個值,然後與原RDD中的K組成一個新的KV對。

val rdd = sc.parallelize(List((1, 2), (3, 4), (3, 6)))

val rdd2 = rdd.reduceByKey((x, y) => x + y)

rdd2.foreach(x => print(x + " "))

這裏表示對相同K的V做求和計算,如(3,4)和(3,6),這裏K相同,V求和爲10,組成一個新的KV對爲(3,10), 這裏 reduce((x,y)=>x+y) 等同爲 reduce(_ + _)

結果:

(1,2) (3,10)


union

將兩個RDD中的數據集進行合併,最終返回兩個RDD的並集,若RDD中存在相同的元素也不會去重

val rdd = sc.parallelize(1.to(5))

val rdd1 = sc.parallelize(2 to 4)

val rdd2 = rdd.union(rdd1)

rdd2.foreach(x => print(x + " "))

println("分區個數:" + rdd2.partitions.size)

rdd是1 2 3 4 5,rdd1是2 3 4,兩個RDD都爲一個默認分區

注意:雖然合併爲一個數據集RDD,但是合併後的RDD有兩個分區,該操作後分區數=兩個RDD分區數之和

最後一行代碼是查看一個RDD的分區數

結果:

1 2 3 4 5

2 3 4


intersection
這個是取兩個RDD的交集
val rdd = sc.parallelize(1.to(5))
val rdd1 = sc.parallelize(2 to 7)
val rdd2 = rdd.intersection(rdd1)
rdd2.foreach(x => print(x + " "))
這裏的交集,最後結果RDD的分區數不固定
結果:
2 3 4 5

distinct
去重
val rdd = sc.parallelize(List(1, 1, 2, 5, 2, 9, 6, 1))
val distinctRDD=rdd.distinct()
distinctRDD.foreach(x => print(x + " "))
結果:
1 6 9 5 2

cartesian
對兩個RDD中所有元素進行笛卡爾積操作
val rdd = sc.parallelize(1.to(3))
val rdd1 = sc.parallelize(2 to 4)
val rdd2 = rdd.cartesian(rdd1)
rdd2.foreach(x => print(x + " "))
這裏原來的RDD的分區,執行該操作後分區數=rdd1的分區數 * rdd2的分區數
結果:
(1,2) (1,3) (1,4) (2,2) (2,3) (2,4) (3,2) (3,3) (3,4)


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