RDD運算元

m0_48714980發表於2020-11-10

一、轉換運算元、
(1)cartesian
RDD1.cartesian(RDD2) 返回RDD1和RDD2的笛卡兒積,這個開銷非常大
val rdd1 = sc.parallelize(List(1,2,3))
val rdd2 = sc.makeRDD(List(“a”,“b”,“c”))
val cartesianRDD = rdd1.cartesian(rdd2)
cartesianRDD.collect().foreach(println)
(1,a)
(1,b)
(1,c)
(2,a)
(2,b)
(2,c)
(3,a)
(3,b)
(3,c)

(2)distinct
distinct用於去重, 我們生成的RDD可能有重複的元素,使用distinct方法可以去掉重複的元素, 不過此方法涉及到混洗,操作開銷很大
val rdd1 = sc.makeRDD(List(“aa”,“aa”,“bb”,“cc”,“dd”))
val rdd2 = rdd1.distinct()
rdd2.collect().foreach(println)
cc
bb
aa
dd
(3)filter
包含zks的行的內容給找出來
in//
aa bb cc aa aa aa dd dd ee ee ee ee
ff aa bb zks
ee kks
cc zz zks
cc ff
pp kks

val rdd1 = sc.textFile(“in”).filter(x=>x.contains(“ks”))
rdd1.collect().foreach(println)
ff aa bb zks
ee kks
cc zz zks
pp kks

(4)flatMap
有時候,我們希望對某個元素生成多個元素,實現該功能的操作叫作 flatMap()
faltMap的函式應用於每一個元素,對於每一個元素返回的是多個元素組成的迭代器(想要了解更多,請參考scala的flatMap和map用法)
val rdd1 = sc.textFile(“in”)
val rdd2 = rdd1.flatMap(x=>x)
rdd2.collect().foreach(println)

(5)intersection
RDD1.intersection(RDD2) 返回兩個RDD的交集,並且去重
intersection 需要混洗資料,比較浪費效能
al rdd1 = sc.makeRDD(List(“aa”, “aa”, “bb”, “cc”, “dd”))
val rdd2 = sc.makeRDD(List(“aa”, “ff”, “bb”))
val intersectionRDD = rdd1.intersection(rdd2)
intersectionRDD.collect().foreach(println)
bb
aa

(6)map
map() 接收一個函式,把這個函式用於 RDD 中的每個元素,將函式的返回結果作為結果RDD程式設計 | 31
RDD 中對應元素的值 map是一對一的關係
val rdd1 = sc.textFile(“D:\testhdfs\sparkJava\in\test”)
//val rdd2 = rdd1.map((,1)).reduceByKey(+_)
val rdd2 = rdd1.map(x=>x.split(" "))
val rdd3 = rdd2.collect().foreach(x=>x.foreach(println))/
//rdd1.collect().foreach(x=>x.foreach(x=>println(x)))

(7)subtract
RDD1.subtract(RDD2),返回在RDD1中出現,但是不在RDD2中出現的元素,不去重
val rdd1 = sc.makeRDD(Array(“aa”,“aa”,“bb”,“cc”))
val rdd2 = sc.makeRDD(Array(“aa”,“aa”,“bb”))
val subtractRDD = rdd1.subtract(rdd2)
subtractRDD.collect().foreach(println)
cc

(8)union
兩個RDD進行合併
val rdd1 = sc.makeRDD(Array(“aa”,“aa”,“bb”,“cc”))
val rdd2 = sc.makeRDD(Array(“aa”,“aa”,“bb”))
val subtractRDD = rdd1.subtract(rdd2)
subtractRDD.collect().foreach(println)
cc

(9)cogroup
groupByKey是對單個 RDD 的資料進行分組,還可以使用一個叫作 cogroup() 的函式對多個共享同一個鍵的 RDD 進行分組
例如
RDD1.cogroup(RDD2) 會將RDD1和RDD2按照相同的key進行分組,得到(key,RDD[key,Iterable[value1],Iterable[value2]])的形式
cogroup也可以多個進行分組
例如RDD1.cogroup(RDD2,RDD3,…RDDN), 可以得到(key,Iterable[value1],Iterable[value2],Iterable[value3],…,Iterable[valueN])
案例,scoreDetail存放的是學生的優秀學科的分數,scoreDetai2存放的是剛剛及格的分數,scoreDetai3存放的是沒有及格的科目的分數,我們要對每一個學生的優秀學科,剛及格和不及格的分數給分組統計出來
val scoreDetail = sc.parallelize(List((“xiaoming”,95),(“xiaoming”,90),(“lihua”,95),(“lihua”,98),(“xiaofeng”,97)))
val scoreDetai2 = sc.parallelize(List((“xiaoming”,65),(“lihua”,63),(“lihua”,62),(“xiaofeng”,67)))
val scoreDetai3 = sc.parallelize(List((“xiaoming”,25),(“xiaoming”,15),(“lihua”,35),(“lihua”,28),(“xiaofeng”,36)))

val cogroupRDD = scoreDetail.cogroup(scoreDetai2)

//cogroupRDD.collect().foreach(println)
cogroupRDD.collect().foreach(x=>{
val value = x._1
val key = x._2
val shuzu1 = key._1
val shuzu2 = key._2
shuzu1.foreach(shuzu1=>{
shuzu2.foreach(shuzu2=>println(value,shuzu1,shuzu2))
})
}
(xiaoming,90,65)
(lihua,95,63)
(lihua,95,62)
(lihua,98,63)
(lihua,98,62)
(xiaofeng,97,67)

(10)flatMapToPair
類似於xxx連線 mapToPair是一對一,一個元素返回一個元素,而flatMapToPair可以一個元素返回多個,相當於先flatMap,在mapToPair
例子: 將每一個單詞都分成鍵為
val rdd1 = sc.textFile(“in”)
val rdd2 = rdd1.flatMap(x=>x.split("\s+"))
val mapRDD = rdd2.map((_,1))
mapRDD.collect().foreach(println)
(aa,1)
(bb,1)
(cc,1)
(aa,1)
(aa,1)
(aa,1)
(dd,1)
(dd,1)
(ee,1)\

(11)foldByKey
該函式用於RDD[K,V]根據K將V做摺疊、合併處理,其中的引數zeroValue表示先根據對映函式將zeroValue應用於V,進行初始化V,再將對映函式應用於初始化後的V.
foldByKey可以參考我之前的scala的fold的介紹
與reduce不同的是 foldByKey開始摺疊的第一個元素不是集合中的第一個元素,而是傳入的一個元素
val rdd1 = sc.makeRDD(Array((“A”,0),(“A”,2),(“B”,1),(“c”,1)))
val foldByKeyRDD = rdd1.foldByKey(1)(+)
foldByKeyRDD.collect().foreach(println)
//將rdd1中每個key對應的V進行累加,注意zeroValue=0,需要先初始化V,對映函式為+操
//作,比如(“A”,0), (“A”,2),先將zeroValue應用於每個V,得到:(“A”,0+0), (“A”,2+0),即:
//(“A”,0), (“A”,2),再將對映函式應用於初始化後的V,最後得到(A,0+2),即(A,2)
(c,2)
(A,4)
(B,2)

(12)groupByKey
groupByKey會將RDD[key,value] 按照相同的key進行分組,形成RDD[key,Iterable[value]]的形式, 有點類似於sql中的groupby,例如類似於mysql中的group_concat
例如這個例子, 我們對學生的成績進行分組
val scoreDetail = sc.parallelize(List((“xiaoming”,75),(“xiaoming”,90),(“lihua”,95),(“lihua”,100),(“xiaofeng”,85)))
val groupByKeyRDD = scoreDetail.groupByKey()
//groupByKeyRDD.collect().foreach(println)
groupByKeyRDD.collect().foreach(x=>{
val key = x._1
val value = x._2
value.foreach(value=>println(key,value))
})

(xiaoming,75)
(xiaoming,90)
(lihua,95)
(lihua,100)
(xiaofeng,85)\

(13)join fullOuterJoin leftOuterJoin rightOuterJoin
RDD1.join(RDD2)
可以把RDD1,RDD2中的相同的key給連線起來,類似於sql中的join操作
fullOuterJoin
和join類似,不過這是全連線
rightOuterJoin
對兩個 RDD 進行連線操作,類似於sql中的右外連線,存在的話,value用的Some, 不存在用的None,具體的看上面的圖和下面的程式碼即可
val rdd1 = sc.parallelize(Array((1,2),(3,4),(3,5),(4,5)))
val rdd2 = sc.parallelize(Array((1,2),(3,4),(5,6)))
val joinRDD = rdd1.join(rdd2)
val joinRDD1 = rdd1.fullOuterJoin(rdd2)
val joinRDD2 = rdd1.leftOuterJoin(rdd2)
val joinRDD3 = rdd1.rightOuterJoin(rdd2)
joinRDD.collect().foreach(x=>print(x+","))
println("*********")
joinRDD1.collect().foreach(x=>print(x+","))
println("*********")
joinRDD2.collect().foreach(x=>print(x+","))
println("*********")
joinRDD3.collect().foreach(x=>print(x+","))

(1,(2,2)),(3,(4,4)),(3,(5,4)),*********
(1,(Some(2),Some(2))),(3,(Some(4),Some(4))),(3,(Some(5),Some(4))),(4,(Some(5),None)),(5,(None,Some(6))),*********
(1,(2,Some(2))),(3,(4,Some(4))),(3,(5,Some(4))),(4,(5,None)),*********
(1,(Some(2),2)),(3,(Some(4),4)),(3,(Some(5),4)),(5,(None,6)),

(14)mapToPair
將每一行的第一個單詞作為鍵,1 作為value建立pairRDD
val lines = sc.textFile(“in”)
val mapRDD = lines.map(x=>(x.split("\s+")(0),1))
mapRDD.collect().foreach(println)
(aa,1)
(ff,1)
(ee,1)
(cc,1)
(cc,1)
(pp,1)

(15)reduceByKey
接收一個函式,按照相同的key進行reduce操作,類似於scala的reduce的操作
例如RDD {(1, 2), (3, 4), (3, 6)}進行reduce
val rdd1 = sc.parallelize(List((1,2),(3,4),(5,6),(1,6),(3,8)))
//val rdd2 = rdd1.reduceByKey(+)
val rdd2 = rdd1.reduceByKey((x,y)=>(x+y))
rdd2.collect().foreach(println)
println("*********************")
val rdd3 = sc.textFile(“in”)
val rdd4 = rdd3.flatMap(.split(" ")).map((,1)).reduceByKey(+)
rdd4.collect().foreach(println)

(aa,1)
(ff,1)
(ee,1)
(cc,1)
(cc,1)
(pp,1)

(16)sortByKey
SortByKey用於對pairRDD按照key進行排序,第一個引數可以設定true或者false,預設是true
val rdd1 = sc.makeRDD(Array((1,2),(2,5),(9,5),(1,8),(7,6)))
val sortbykeyRDD = rdd1.sortByKey()
sortbykeyRDD.collect().foreach(println)
(aa,1)
(ff,1)
(ee,1)
(cc,1)
(cc,1)
(pp,1)

(17)subtract
RDD1.subtract(RDD2),返回在RDD1中出現,但是不在RDD2中出現的元素,不去重
val rdd1 = sc.makeRDD(Array((“xiaoming”,24),(“xiaohong”,24),(“xia”,24)))
val rdd2 = sc.makeRDD(Array((“xiaoming”,24),(“xiaohong”,26),(“xu”,24)))
val subtractRDD = rdd1.subtract(rdd2)
subtractRDD.collect().foreach(println)
(xia,24)
(xiaohong,24)

二、action運算元

(1)collectAsMap
將pair型別(鍵值對型別)的RDD轉換成map
val countByKeyRDD = sc.parallelize(Array((1,2),(2,3),(1,3),(3,4),(3,5),(3,7)))
countByKeyRDD.collectAsMap()
(1->2,2->1,3->3)

(2)collect
rdd.collect() 返回 RDD 中的所有元素
val sc = new SparkContext(conf)
sc.parallelize(Array(1, 2, 4, 5)).collect().foreach(x => print(x + " "))
1 2 4 5

(3)countByKey
val countByKeyRDD = sc.parallelize(Array((1,2),(2,3),(1,3),(3,4),(3,5),(3,7)))
countByKeyRDD.countByKey().foreach(println)
(1,2)
(2,1)
(3,3)

(4)countByValue
各元素在 RDD 中出現的次數 返回{(key1,次數),(key2,次數),…(keyn,次數)}
sc.makeRDD(Array(1, 1, 2, 2, 8, 8, 6, 6, 6)).countByValue())
]Map(1 -> 2, 2 -> 2, 6 -> 3, 8 -> 2)

(5)count()
rdd.count() 返回 RDD 中的元素個數
println(sc.makeRDD(Array(1, 2, 3)).count())
3

(6)first
返回第一個元素
println( sc.makeRDD(List(1,2,4)).first())
1

(7)reduce
rdd.reduce(func)
並行整合RDD中所有資料, 類似於是scala中集合的reduce
println(sc.parallelize(List(1, 2, 4, 8)).reduce(_ + _))
15

(8) take
rdd.take(n)返回第n個元素
sc.parallelize(Array(1, 2, 4, 5)).take(1).foreach(x=>print(x+" "))
1

(9)takeOrder
rdd.take(n)
對RDD元素進行升序排序,取出前n個元素並返回,也可以自定義比較器(這裡不介紹),類似於top的相反的方法 sc.parallelize(List(5,7,2,1)).takeOrdered(3).foreach(println)
1
2
5

(10)top
sc.parallelize(List(5, 1, 9, 3, 7, 8)).top(3)).foreach(println)
9
8
7

(11)mapPartitions
mapPartitions操作鍵值對 把(i,j) 變成(i,j*j)
val rdd1 = sc.makeRDD(Array(1,2,3,4,5,6))
val mapPartitionsRDD = rdd1.mapPartitions(item => {
item.map(_ * 2)
})
mapPartitionsRDD.collect().foreach(println)

2
4
6
8
10
12

(12)mapPartitionsWithIndexDemo
與mapPartitionWithIndex類似,也是按照分割槽進行的map操作,不過mapPartitionsWithIndex傳入的引數多了一個分割槽的值,下面舉個例子,為統計各個分割槽中的元素 (稍加修改可以做統計各個分割槽的數量)
val rdd1 = sc.makeRDD(Array(1, 2, 3, 4, 5, 6),4)
val IndexRDD = rdd1.mapPartitionsWithIndex((index,item)=>(item.map((_,“分割槽號,”+index))))
IndexRDD.collect().foreach(println)
IndexRDD.saveAsTextFile(“xia”)
(1,分割槽號,0)
(2,分割槽號,1)
(3,分割槽號,1)
(4,分割槽號,2)
(5,分割槽號,3)
(6,分割槽號,3)

相關文章