瞭解下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
val rdd2 = rdd.intersection(rdd1)