有没有想过为什么整个对象B需要被序列化?
object A{
def main(args:Array[String])= {
val conf = new SparkConf().setAppName("test").setMaster("local")
val sc = new SparkContext(conf)
val rdd=sc.makeRDD(Seq(1,2,3,4,5,6,7))
val b=new B
b.add(rdd)
}
}
class B {
val s="456"
def add=(rdd:RDD[Int])=>{
rdd.map(e=>e+" "+s).foreach(println)
}
}
关于“对象不可序列化”的例外情况:
Serialization stack:
- object not serializable (class: B, value: B@1fde4f40)
- field (class: B$$anonfun$add$1, name: $outer, type: class B)
- object (class B$$anonfun$add$1, <function1>)
- field (class: B$$anonfun$add$1$$anonfun$apply$1, name: $outer, type: class B$$anonfun$add$1)
- object (class B$$anonfun$add$1$$anonfun$apply$1, <function1>)
答案 0 :(得分:1)
请参阅链接的Task not serializable: java.io.NotSerializableException when calling function outside closure only on classes not objects。你的语法是什么
def add=(rdd:RDD[Int])=>{
rdd.map(e=>e+" "+s).foreach(println)
}
真的意味着
def addReal(): RDD[Int] => Unit = (rdd: RDD[Int]) => {
val rddFunc: Int => String = e => e + " " + s
rdd.map(rddFunc).foreach(println)
}
现在rddFunc
captures s
来自其包含对象B
的上下文,这是通过实际捕获整个对象B
来完成的序列化的。
除了链接答案中列出的选项之外,还有什么可以帮助您将add
更改为
def add(rdd:RDD[Int]) = {
val localS = s
rdd.map(e => e + " " + localS).foreach(println)
}
主要技巧是引入localS
变量,强制rddFunc
仅捕获它而不是整个B
。
旁注 :在上面的代码中,我还更改了add
的签名
def add():Function1[RDD[Int], Unit]
你必须
def add(rdd:RDD[Int]):Unit
在add
返回您立即致电的功能的情况下,没有任何好处。