Spark RDD基本操作

來源:互聯網
上載者:User
Spark RDD Scala語言編程

RDD(Resilient Distributed Dataset)是一個不可變的分布式對象集合, 每個rdd被分為多個分區, 這些分區運行在叢集的不同節點上。rdd支援兩種類型的操作:轉化(trainsformation)和行動(action), Spark只會惰性計算rdd, 也就是說, 轉化操作的rdd不會立即計算, 而是在其第一次遇到行動操作時才去計算, 如果想在多個行動操作中複用一個rdd, 可以使用RDD.persist()讓Spark把這個rdd緩衝下來。 0. 初始化SparkContext

import org.apache.spark.{SparkConf, SparkContext}val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("spark-rdd-demo"))
1. 建立RDD

Spark提供了2種建立RDD的方式: 1.1 讀取外部資料集

val lines = sc.parallelize(List("Java", "Scala", "C++"))
1.2 在磁碟機程式中對一個集合進行並行化
val lines = sc.textFile("hdfs://dash-dev:9000/input/test.txt")
2. RDD操作 2.1 轉化操作

RDD的轉化操作是返回新RDD的操作, 常用轉化操作總結如下:

表1: 對一個資料為{1,2,3,3}的RDD進行基本的轉化操作

函數名 目的 樣本 結果
map() 將函數應用於RDD中每個元素, 將傳回值構成新的RDD rdd.map(x=>x+1) {2,3,4,5}
flatMap() 將函數應用於RDD中的每個元素, 將返回的迭代器的所有內容構成新的RDD, 常用來切分單詞 rdd.flatMap(x=>x.to(2)) {1,2,2}
filter() 返回一個通過傳入給filter()的函數的元素組成的RDD rdd.filter(x=> x>2) {3,3}
distinct() 去重 rdd.distinct() {1,2,3}
sample(withReplacement, fraction, [seed]) 對RDD採樣, 以及是否替換 rdd.sample(false, 0.5) 非確定的

表2: 對資料分別為{1,2,3}和{2,3,4}RDD進行針對2個RDD的轉化操作

函數名 目的 樣本 結果
union() 求2個RDD的並集 rdd.union(other) {1,2,3,4}
intersection() 求2個RDD的交集 rdd.intersection(other) {2,3}
subtract() 求2個RDD的差集 rdd.subtract(other) {1}
cartesian() 求2個RDD的笛卡爾積 rdd.cartesian(other) {1,2}, {1,3}, {1,4}…{3,4}
sample(withReplacement, fraction, [seed]) 對RDD採樣, 以及是否替換 rdd.sample(false, 0.5) 非確定的
2.2 行動操作

RDD的行動操作會把最終求得的結果返回磁碟機程式, 或者寫入外部儲存系統中。

表3: 對一個資料為{1,2,3,3}的RDD進行基本RDD的行動操作

函數名 目的 樣本 結果
redcue() 並行整合RDD中的所有元素 rdd.reduce((x, y) => x+y) 9
collect() 返回RDD中的所有元素 rdd.collect() {1,2,3,4}
count() 求RDD中的元素個數 rdd.count() 4
countByValue() 各元素在RDD中出現的次數 rdd.countByValue() {1,1}, {2, 1}, {3,2}
take(n) 從RDD中返回n個元素 rdd.take(2) {1,2}
top(n) 從RDD中返回前n個元素 rdd.top(3) {3,3,2}
foreach(func) 對RDD中的每個元素使用給定的函數 rdd.foreach(print) 1,2,3,3
2.3 向Spark傳遞函數

Spark的大部分轉化和行動操作都要依賴於使用者傳遞的函數來計算, 當傳遞的對象是某個對象的成員, 或者包含了對某個對象中一個欄位的引用時(如self.field), Spark就會把整個對象發送到工作節點上--這比你本意想傳遞的東西大太多了。替代的方案是,把你需要的欄位從對象中拿出來放到一個局部變數中, 然後傳遞這個局部變數:

class SearchFunctions(val query: String) {    def isMatch(s: String): Boolean = {        s.contains(query)    }    def getMatchesFunctionReference(rdd: RDD[String]): RDD[String] = {        // 問題:"isMatch"表示"this.isMatch", 因此會傳遞整個this        rdd.map(isMatch)    }    def getMatchesFieldReference(rdd: RDD[String]): RDD[String] = {        // 問題: "query"表示"this.query", 因此會傳遞整個this        rdd.map(x => x.split(query))    }    def getMatchesNoReference(rdd: RDD[String]): RDD[String] = {        // 安全:只把我們需要的欄位拿出來放入局部變數中        val localQuery = this.query        rdd.map(x => x.split(localQuery))    }}

另外, 要注意的是, Spark要求我們傳入的函數及其應用的資料是可序列化的(實現了Java的Serializable介面), 否則會出現NotSerializableException。

作者 @wusuopubupt
2016年11月11日

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.