Spark scala api(一)RDD編程

基礎

初始化spark

val conf = new SparkConf().setAppName("wordcount")
val sc = new SparkContext(conf)

轉化操作和行動操作的區別在於spark計算rdd的方式不同,只有在第一次在一個行動操作中用到轉化操作中的rdd時,纔會真正計算這些rdd。

創建rdd

// 驅動器程序對一個集合進行並行化
val lines = sc.parallelize(List("pandas","i like pandas"))
//讀取外部數據集
val lines = sc.textFile("/path/to/README.md")

rdd操作

  • 轉化操作 例如filter()
    filter不會改變已有的inputRDD的數據

    val errorsRDD = inputRDD.filter(line => line.contains(“error”))

  • 行動操作 例如count()

    println("Input had " + badLinesRDD.count() + “concerning lines”)
    println(“Here are 10 examples:”)
    badLinesRDD.take(10).foreach(println)

向spark傳遞函數

我們可以把定義的內聯函數,方法的引用或者靜態方法傳遞給Spark

class SearchFunctions(val query: String){
	def isMatch(s: String):Boolean = {
	 	s.contains(query)
	 	}
	 }
	 //傳遞整個對象
	 def getMatchesFunctionReference(rdd: RDD[String]) :RDD[String] = {
	 	rdd.map(isMatch)
	 }
	 //傳遞整個對象
	 def getMatchesFieldReference(rdd: RDD[String]): RDD[String]= {
	 	rdd.map( x => x.split(query))
	 }
	 //傳遞局部變量
	 def getMatchesNoReference(rdd: RDD[String]: RDD[String] ) = {
	 	val query_ = this.query
	 	rdd.map(x => x.split(query_))

常見轉化操作和行動操作

轉化操作

  • map(): 接收一個函數,把這個函數作用於RDD中的每一個元素,將函數的返回結果作爲結果RDD中對應的值

    val result = input.map( x => x*x)

  • filter():接收一個函數,並將RDD中滿足該函數的元素放入新的RDD中返回

    val result = input.filter( x => x.contains(“a”))

  • flatMap():將接收到的函數分別應用到輸入RDD中的每一個元素中,返回一個返回值序列的迭代器

    val words = input.flatMap(line => line.spilt(" "))

  • 僞集合操作
    distinct() : RDD中最常缺失的是集合的唯一性,常常有重複的元素,RDD.distinct()轉化操作可以生成一個只包含不同元素的新RDD,但是此操作開銷很大,需要將所有數據通過網絡shuffle。
    union(): 返回一個包含兩個RDD中所有元素的RDD,含有重複元素
    intersection():只返回兩個RDD中所共有的元素,運行時會去掉所有重複的元素,單個RDD中的重複元素也會去掉,需要shuffle,性能差很多。
    subtract():需要數據混洗,接收一個RDD,並去掉第一個RDD中與接收RDD相同的元素
    cartesian():求笛卡爾積,所有可能的組合

行動操作

  • reduce():接收一個函數作爲參數,這個函數要操作兩個相同元素類型的RDD數據並返回一個同樣類型的新元素
    val sum = rdd.reduce((x,y) => x + y)
  • fold(): 和reduce一樣,但是需要提供初始值
  • aggregate():返回值類型可以與所操作的RDD類型不同
    計算RDD的平均值 通過一個函數將RDD中的元素合併起來放入累加器,然後用第二個函數將累加器兩兩合併
val result = input.aggregate((0,0))(
					(acc , value) => (acc._1 + value ,  acc._2 + 1),
					(acc1, acc2) => (acc._1 +acc2._1, acc1._2 + acc2._2))
val avg = result._1/result._2.toDouble
  • collect()
    collect()將整個RDD的內容返回,將數據複製到驅動器進程中,要求所有數據都能一同放入單臺機器的內存中,通常在單元測試中使用
  • take(n)
    返回RDD中的n個元素,不均衡
  • top(n) 如果爲數據定義了順序,可以使用top()從RDD中獲取前幾個元素,也可以使用自己的比較函數
  • takeSample(withReplacement,num,[seed]) 從RDD返回任意一些元素
  • foreach()
  • count()
  • countByValue()

不同類型RDD之間轉化

mean(),variance()只能用在數值RDD,join()只能用在鍵值對RDD
在scala中,將RDD轉爲特定函數的RDD是由隱式轉換來自動處理的
import org.apache.spark.SparkContext._

持久化

RDD都是惰性求值的
有時需要多次使用同一個RDD
persist()默認會把數據以序列化的形式緩存在JVM的堆空間中
5個級別:MEMORY_ONLY,MEMORY_ONLY_SER,MEMORY_AND_DISK,MEMORY_AND_DISK_SER,DISK_ONLY
import org.apache.spark.storage.StorageLevel
rdd.persist(StorageLevel.DISK_ONLY)
unpersist()手動釋放持久化的RDD

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