【问题标题】:Avoid "Task not serialisable" with nested method in a class在类中使用嵌套方法避免“任务不可序列化”
【发布时间】:2014-05-19 08:26:09
【问题描述】:

我了解访问超出闭包范围的字段或方法时通常会出现的“任务不可序列化”问题。

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

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 而不是 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)     
  } 
} 

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

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

【问题讨论】:

  • 我也看到了这一点,一旦他们更改为 val's not defs 就可以了!感谢您分享这一观察结果。

标签: apache-spark


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2017-06-29
    • 2018-10-07
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    • 2012-08-09
    • 1970-01-01
    相关资源
    最近更新 更多