2014-05-19 42 views
6

我理解當訪問超出閉包範圍的字段或方法時出現的通常的「任務不可序列化」問題。在類中使用嵌套方法避免「任務不可序列化」

爲了解決這個問題,我通常定義的這些字段/方法的本地拷貝,從而避免了需要序列全班同學:

class MyClass(val myField: Any) { 
    def run() = { 
    val f = sc.textFile("hdfs://xxx.xxx.xxx.xxx/file.csv") 

    val myField = this.myField 
    println(f.map(_ + myField).count) 
    } 
} 

現在,如果我在run方法定義一個嵌套函數,它不能被序列化:

class MyClass() { 
    def run() = { 
    val f = sc.textFile("hdfs://xxx.xxx.xxx.xxx/file.csv") 

    def mapFn(line: String) = line.split(";") 

    val myField = this.myField 
    println(f.map(mapFn(_)).count) 

    } 
} 

,因爲我認爲「mapFn」將是範圍... 更奇怪的是,如果我定義mapFn是一個VAL而不是閃避,那麼它的作品,我不明白:

class MyClass() { 
    def run() = { 
    val f = sc.textFile("hdfs://xxx.xxx.xxx.xxx/file.csv") 

    val mapFn = (line: String) => line.split(";") 

    println(f.map(mapFn(_)).count)  
    } 
} 

這與Scala表示嵌套函數的方式有關嗎?

什麼是處理這個問題的建議方法? 避免嵌套函數?

+0

我也看到這一點,一旦他們改變爲val的不defs它的作品!所以謝謝分享這個觀察。 – MahdeTo

回答

1

是不是在工作的方式,以便在第一種情況下f.map(mapFN(_))相當於f.map(new Function() { override def apply(...) = mapFN(...) })和在第二個它只是f.map(mapFN)?當你使用def聲明一個方法時,它可能只是一些匿名類中的一個方法,對封閉類有一個隱含的$outer引用。但是map需要一個Function,所以編譯器需要包裝它。在包裝器中,您只需引用該匿名類的某些方法,但不涉及實例本身。如果使用val,則直接引用您傳遞給map的功能。我不知道這個,只是想着大聲.​​..