我是Scala的新手。为什么“map”函数不可序列化?如何使其可序列化?例如,如果我的代码如下所示:
val data = sc.parallelize(List(1,4,3,5,2,3,5))
def myfunc(iter: Iterator[Int]) : Iterator[Int] = {
val lst = List(("a", 1),("b", 2),("c",3), ("a",2))
var res = List[Int]()
while (iter.hasNext) {
val cur = iter.next
val a = lst.groupBy(x => x._1).mapValues(_.size)
//val b= a.map(x => x._2)
res = res ::: List(cur)
}
res.iterator
}
data.mapPartitions(myfunc).collect
如果我取消注释该行
val b= a.map(x => x._2)
代码返回异常:
org.apache.spark.SparkException: Task not serializable
Caused by: java.io.NotSerializableException: scala.collection.immutable.MapLike$$anon$2
Serialization stack:
- object not serializable (class: scala.collection.immutable.MapLike$$anon$2, value: Map(1 -> 3))
- field (class: $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC, name: a, type: interface scala.collection.immutable.Map)
非常感谢。
答案 0 :(得分:56)
众所周知的scala bug:https://issues.scala-lang.org/browse/SI-7005 Map#mapValues不可序列化
我们的Spark应用中存在此问题,map(identity)
解决了问题
rdd.groupBy(_.segment).mapValues(v => ...).map(identity)
答案 1 :(得分:4)
下面提供了mapValues函数的实际实现,正如您所看到的那样,它不是可序列化的,只创建一个视图而不是正确的数据存在,因此您收到此错误。情境明智的mapValues有很多优点。
protected class MappedValues[C](f: B => C) extends AbstractMap[A, C] with DefaultMap[A, C] {
override def foreach[D](g: ((A, C)) => D): Unit = for ((k, v) <- self) g((k, f(v)))
def iterator = for ((k, v) <- self.iterator) yield (k, f(v))
override def size = self.size
override def contains(key: A) = self.contains(key)
def get(key: A) = self.get(key).map(f)
}
答案 2 :(得分:1)
您是否尝试在应用程序中运行相同的代码?我怀疑这是火花壳的一个问题。如果你想让它在spark shell中运行,那么你可以尝试将myfunc
的定义及其应用程序包含在大括号中,如下所示:
val data = sc.parallelize(List(1,4,3,5,2,3,5))
val result = {
def myfunc(iter: Iterator[Int]) : Iterator[Int] = {
val lst = List(("a", 1),("b", 2),("c",3), ("a",2))
var res = List[Int]()
while (iter.hasNext) {
val cur = iter.next
val a = lst.groupBy(x => x._1).mapValues(_.size)
val b= a.map(x => x._2)
res = res ::: List(cur)
}
res.iterator
}
data.mapPartitions(myfunc).collect
}