我理解通常在访问字段或超出闭包范围的方法时出现的"任务不可序列化"问题.
为了解决这个问题,我通常会定义这些字段/方法的本地副本,这样就无需序列化整个类:
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表示嵌套函数的方式有关吗?
处理这个问题的推荐方法是什么?避免嵌套函数?
它的工作方式不是在第一种情况下f.map(mapFN(_))
相当于f.map(new Function() { override def apply(...) = mapFN(...) })
,在第二种情况下只是f.map(mapFN)
?当您使用它声明一个方法时,def
它可能只是某个匿名类中的方法,并且隐式$outer
引用封闭类。但map
需要一个,Function
所以编译器需要包装它。在包装器中,您只需引用该匿名类的某些方法,而不是实例本身。如果使用val
,则可以直接引用传递给 的函数map
。我对此不太确定,只是大声思考......
归档时间: |
|
查看次数: |
229 次 |
最近记录: |