閱讀目錄
RDD
1、RDD(Resilient Distributed Datasets)彈性的分佈式數據集,又稱Spark core,它代表一個只讀的、不可變、可分區,裏面的元素可分佈式並行計算的數據集。
2、RDD主要有兩大類操作,分別爲轉換(Transformations)和行動(Actions),轉換操作通過某種函數將一個RDD轉換爲一個新的RDD,但是轉換操作是懶操作,不會立即執行計算。而行動操作是用於觸發轉換操作的操作,這個時候纔會真正開始計算。
3、常用的Transformations函數
函數 | 描述 |
---|---|
map(func) | 對RDD數據集中的每個元素都使用func,返回一個新的RDD |
filter(func) | 對RDD數據集中的每個元素都使用func,返回使func爲true的元素構成的RDD |
flatMap(func) | 和map類似,但是flatMap生成的是多個結果 |
union(otherDataset) | 返回一個新的dataset,包含源dataset和給定dataset的元素的集合 |
grouplyKey(num Tasks) | 返回( K,Seq[V] ),根據相同的鍵分組 |
reducclykey(func [numTasks]) | 用一個給定的func作用在grouplyKey 而產生的(K,Seq[V),比如求和 |
4、常用的Actions函數
函數 | 描述 |
---|---|
reduce( func) | 通過函數func聚集數據集中的所有元素。func函數接收兩個參數,返回一個值 |
collect() | 返回數據集中所有的元素 |
count() | 返回數據集中所有元素的個數 |
first0) | 返回數據集中的第一個元素 |
take(n) | 返回前n個元素 |
saveAsTextFile(path) | 將數據集的元素以textfile的形式保存到本地文件系統、hdfs或者任何其他Hadoop支持的文件系統。Spark將會調用每個元素的toString方法,並將它轉換爲文件中的一行文本 |
foreach(func) | 對數據集中的每個元素都執行函數func |
一、創建RDD
1、從對象集合創建RDD
spark可以通過parallelize()或makeRDD()方法將一個對象集合轉化爲RDD
scala> val rdd=sc.parallelize(List(1,2,3,4,5,6))
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24
scala> val rdd=sc.makeRDD(List(1,2,3,4,5,6))
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[1] at makeRDD at <console>:24
從返回信息可以看出,上述創建的RDD中存儲的是Int類型數據,實際上,RDD也是一個集合,與常用的List集合不同的是,RDD集合的數據分佈在多臺計算機上。
2、從外部存儲創建RDD
(1)從HDFS文件創建RDD
直接通過textFile命令讀取HDFS文件的位置即可。
scala> val rdd=sc.textFile("/WordCount/words.txt")
rdd: org.apache.spark.rdd.RDD[String] = /WordCount/words.txt MapPartitionsRDD[3] at textFile at <console>:24
scala> rdd.collect
res0: Array[String] = Array(hello hadoop, hello spark, hello scala)
(2)從Linux本地文件創建RDD
本地文件讀取也是通過sc.textFile(“路徑”)的方法,在路徑前面加上“file://”表示從本地Linux文件系統讀取。
scala> val rdd=sc.textFile("file:///usr/local/spark/words.txt")
rdd: org.apache.spark.rdd.RDD[String] = file:///usr/local/spark/words.txt MapPartitionsRDD[7] at textFile at <console>:24
scala> rdd.collect
res2: Array[String] = Array(hello hadoop, hello spark, hello scala)
從上述rdd.collect的輸出內容可以看到,textFile()方法將源文件中的內容按行拆分成了RDD集合中的多個元素。
二、轉換算子
1、map()算子
map()是一種基礎的RDD轉換操作,它接收一個函數作爲參數,並把這個函數應用於RDD的每個元素,最後將函數的返回結果作爲結果RDD中對應元素的值。
例如,將rdd1中的每個元素加1(_+1等同於x=>x+1)並返回一個名爲rdd2的新RDD:
scala> val rdd1=sc.parallelize(List(1,2,3,4,5))
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[8] at parallelize at <console>:24
scala> val rdd2=rdd1.map(_+1)
rdd2: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[9] at map at <console>:25
scala> rdd2.collect
res3: Array[Int] = Array(2, 3, 4, 5, 6)
2、filter()算子
通過函數對源RDD的每個元素進行過濾,並返回一個新的RDD。
scala> val rdd1=sc.parallelize(List(1,2,3,4,5))
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[10] at parallelize at <console>:24
scala> val rdd2=rdd1.filter(_>3)
rdd2: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[11] at filter at <console>:25
scala> rdd2.collect
res4: Array[Int] = Array(4, 5)
3、flatMap()算子
與map()算子類似,但是每個傳入給函數func的RDD元素會返回0到多個元素,最終會將返回的所有元素合併到一個RDD。
例如:將集合List轉化爲rdd1,然後調用rdd1的flatMap()算子將rdd1的每個元素按照空格分割成多個元素,最終合併所有元素到一個新的RDD。
scala> val rdd1=sc.parallelize(List("hadoop hbase hive" ,"hadoop spark"))
rdd1: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[12] at parallelize at <console>:24
scala> val rdd2=rdd1.flatMap(_.split(" "))
rdd2: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[13] at flatMap at <console>:25
scala> rdd2.collect
res5: Array[String] = Array(hadoop, hbase, hive, hadoop, spark)
4、distinct()算子
distinct()是一個轉換操作,用於RDD的數據去重,去除兩個完全相同的元素,沒有參數。
例如:將flatMap()算子的例子的rdd2去重
scala> rdd2.distinct().collect
res6: Array[String] = Array(spark, hive, hadoop, hbase)
5、groupByKey()算子
groupByKey()是對具有相同鍵的值進行分組,分組常常是爲了對同一組的數據進行計數、統計等。
scala> val rdd1=sc.parallelize(List(("hadoop",1),("hadoop",2),("spark",1),("spark",1)))
rdd1: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[17] at parallelize at <console>:24
scala> val rdd2=rdd1.groupByKey()
rdd2: org.apache.spark.rdd.RDD[(String, Iterable[Int])] = ShuffledRDD[18] at groupByKey at <console>:25
scala> rdd2.collect
res7: Array[(String, Iterable[Int])] = Array((spark,CompactBuffer(1, 1)), (hadoop,CompactBuffer(1, 2)))
6、reduceByKey()算子
reduceByKey()算子的作用對象是元素爲(key,value)形式的RDD,可以將相同的key的元素聚集到一起,最終把所有相同key的元素合併成爲一個元素。
scala> val rdd1=sc.parallelize(List(("hadoop",1),("hadoop",2),("spark",1),("spark",1)))
rdd1: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[19] at parallelize at <console>:24
scala> val rdd2=rdd1.reduceByKey((x,y)=>x+y)
rdd2: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[20] at reduceByKey at <console>:25
scala> rdd2.collect
res8: Array[(String, Int)] = Array((spark,2), (hadoop,3))
7、sortBy()算子
將RDD中的元素按照某個規則進行排序,該算子的第一個參數爲排序函數,第二個參數是一個布爾值,指定升序(默認)或降序。如需要降序排列,則將第二個參數置爲false。
scala> val rdd1=sc.parallelize(List(("hadoop",5),("Spark",7),("scala",3)))
rdd1: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[21] at parallelize at <console>:24
scala> val rdd2=rdd1.sortBy(x=>x._2,false)
rdd2: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[24] at sortBy at <console>:25
scala> rdd2.collect
res9: Array[(String, Int)] = Array((Spark,7), (hadoop,5), (scala,3))
8、union()算子
將兩個RDD合併爲一個新的RDD,主要用於對不同的數據來源進行合併,兩個RDD中的數據類型要保持一致。
scala> val rdd1=sc.parallelize(List(1,2,3))
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[25] at parallelize at <console>:24
scala> val rdd2=sc.parallelize(List(4,5,6))
rdd2: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[26] at parallelize at <console>:24
scala> val rdd3=rdd1.union(rdd2)
rdd3: org.apache.spark.rdd.RDD[Int] = UnionRDD[27] at union at <console>:27
scala> rdd3.collect
res10: Array[Int] = Array(1, 2, 3, 4, 5, 6)
三、行動算子
1、reduce()算子
將數字1-100所組成的集合轉化爲RDD,然後對該RDD進行reduce()算子計算,統計RDD中所有元素的總和。
scala> val rdd1=sc.parallelize(1 to 100)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[29] at parallelize at <console>:24
scala> rdd1.reduce(_+_)
res12: Int = 5050
2、count()算子
統計RDD集合中元素的數量。
scala> val rdd1=sc.parallelize(1 to 100)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[29] at parallelize at <console>:24
scala> rdd1.count
res13: Long = 100
3、take()算子
返回集合中前n個元素組成的數組。
scala> val rdd1=sc.parallelize(1 to 100)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[29] at parallelize at <console>:24
scala> rdd1.take(5)
res14: Array[Int] = Array(1, 2, 3, 4, 5)
四、使用Spark RDD實現單詞計數
我的另一篇博客有介紹 :使用Spark RDD實現單詞計數