Learning Spark筆記3-傳遞函數給Spark

傳遞函數給Spark


大多數的Spark轉換和一些動作都依賴傳遞函數計算數據。


1.Python 


在Python中我們使用3種形式傳遞函數到Spark。對於較短的函數,我們可以傳lambda表達式、通過頂層函數傳遞或定義本地函數。


Example 3-18. Passing functions in Python


word = rdd.filter(lambda s: "error" in s)
def containsError(s):
return "error" in s
word = rdd.filter(containsError)


有一件事需要注意的是,它會序列化函數中的對象。當你傳遞一個函數時,如果該函數是一個對象的成員或包含屬性的引用(例如,self.field),Spark會將整個對象發送給工作節點,這樣的對象肯定要比你需要信息大的多。有些時候,這也可以能會引起你的程序失敗,


Example 3-19. Passing a function with field references (don’t do this!)
class SearchFunctions(object):
def __init__(self, query):
elf.query = query
def isMatch(self, s):
return self.query in s
def getMatchesFunctionReference(self, rdd):
# Problem: references all of "self" in "self.isMatch"
return rdd.filter(self.isMatch)
def getMatchesMemberReference(self, rdd):
# Problem: references all of "self" in "self.query"
return rdd.filter(lambda x: self.query in x)


相反的,只需將您需要的字段從您的對象中提取到一個局部變量中,並將其傳入,就像我們所做的那樣。


class WordFunctions(object):
...
def getMatchesNoReference(self, rdd):
# Safe: extract only the field we need into a local variable
query = self.query
return rdd.filter(lambda x: query in x)




2.Scala


在Scala中,我們可以傳遞定義的內聯函數,引用方法或static。


Example 3-21. Scala function passing


class SearchFunctions(val query: String) {
def isMatch(s: String): Boolean = {
s.contains(query)
}
def getMatchesFunctionReference(rdd: RDD[String]): RDD[String] = {
// Problem: "isMatch" means "this.isMatch", so we pass all of "this"
rdd.map(isMatch)
}
def getMatchesFieldReference(rdd: RDD[String]): RDD[String] = {
// Problem: "query" means "this.query", so we pass all of "this"
rdd.map(x => x.split(query))
}
def getMatchesNoReference(rdd: RDD[String]): RDD[String] = {
// Safe: extract just the field we need into a local variable
val query_ = this.query
rdd.map(x => x.split(query_))
}
}


在Scala中如果出現NotSerializableException,通常都是由一個非序列化類中的方法或屬性引用導致的。請注意,傳遞本地可序列化變量或頂層對象的成員函數是安全的。


3.Java


Example 3-22. Java function passing with anonymous inner class


RDD<String> errors = lines.filter(new Function<String, Boolean>() {
public Boolean call(String x) {
return x.contains("error");
}
});




Example 3-23. Java function passing with named class


class ContainsError implements Function<String, Boolean>() {
public Boolean call(String x) { 
return x.contains("error"); 
}
}


RDD<String> errors = lines.filter(new ContainsError());


編程風格是個人偏好,但是我們發現,頂層命名函數用於組織大型程序通常比較簡單,頂級函數的另一個優點是可以給它們構造函數參數


Example 3-24. Java function class with parameters


class Contains implements Function<String, Boolean>() {
private String query;
public Contains(String query) { this.query = query; }
public Boolean call(String x) { return x.contains(query); }
}
RDD<String> errors = lines.filter(new Contains("error"));




在Java 8中,你也可以使用lambda表達式


Example 3-25. Java function passing with lambda expression in Java 8


RDD<String> errors = lines.filter(s -> s.contains("error"));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章