在类中使用嵌套方法避免"Task not serialisable"

bor*_*rck 6 apache-spark

我理解通常在访问字段或超出闭包范围的方法时出现的"任务不可序列化"问题.

为了解决这个问题,我通常会定义这些字段/方法的本地副本,这样就无需序列化整个类:

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 Code Online (Sandbox Code Playgroud)

现在,如果我在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) 

  } 
} 
Run Code Online (Sandbox Code Playgroud)

我不明白,因为我认为"mapFn"将在范围内...更奇怪的是,如果我将mapFn定义为val而不是def,那么它的工作原理如下:

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)     
  } 
} 
Run Code Online (Sandbox Code Playgroud)

这与Scala表示嵌套函数的方式有关吗?

处理这个问题的推荐方法是什么?避免嵌套函数?

Jac*_* L. 1

它的工作方式不是在第一种情况下f.map(mapFN(_))相当于f.map(new Function() { override def apply(...) = mapFN(...) }),在第二种情况下只是f.map(mapFN)?当您使用它声明一个方法时,def它可能只是某个匿名类中的方法,并且隐式$outer引用封闭类。但map需要一个,Function所以编译器需要包装它。在包装器中,您只需引用该匿名类的某些方法,而不是实例本身。如果使用val,则可以直接引用传递给 的函数map。我对此不太确定,只是大声思考......