Избегайте "задача не сериализуема" с вложенным методом в классе
Я понимаю обычную проблему "задача не сериализуема", которая возникает при доступе к полю или методу, который находится вне области замыкания.
Чтобы исправить это, я обычно определяю локальную копию этих полей / методов, что позволяет избежать необходимости сериализации всего класса:
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 представляет вложенные функции?
Каков рекомендуемый способ решения этой проблемы ? Избегать вложенных функций?
1 ответ:
Разве это не работает таким образом, что в первом случае
f.map(mapFN(_))
эквивалентноf.map(new Function() { override def apply(...) = mapFN(...) })
, а во втором-простоf.map(mapFN)
? Когда вы объявляете метод сdef
, это, вероятно, просто метод в некотором анонимном классе с неявной$outer
ссылкой на заключающий класс. Ноmap
требуетFunction
, поэтому компилятор должен обернуть его. В оболочке вы просто ссылаетесь на некоторый метод этого анонимного класса,но не на сам экземпляр. Если вы используетеval
, у вас есть прямая ссылка на функция, которую вы передаете вmap
. Я не уверен насчет этого, просто думаю вслух...