2017-05-09 56 views
2

我有案例类是这样的:星火集工会复位类变量

case class Ais(NotImportant) 
    extends Serializable { 


    var flag = Ais.Flag.NotFlagged 
    var cluster = Ais.Unknown 
    var visited = false 

    override def toString(): String = { 
    s"$cluster,$flag,$visited" 
    } 
} 

运行我的算法,我结束了(Int,Ais)凡在Ais对象变量包含的信息类型的两个数据集之后。我需要联合他们。对我来说最重要的是var clustervar visited的值。然后在union之后,它们被重置为默认值。

labeledInner.foreach(println(_)) // This is fine 
println("==========") 
labeledOuter.foreach(println(_)) // This is also fine 
println("==========") 
labeledOuter.union(labeledInner).foreach(println(_)) // Here 
               // everything set to default 

我正在运行Spark 2.1和Scala 2.11.8。

回答

3

你不应该用放电时使用的情况下,类可变vars - 这些没有“幸免于难”星火的编码,因此任何不平凡的使用DataSet的(如使用union)触发编码和解码不会保存这些领域。

为什么? Spark具有内置的编码器,用于将对象有效地编码为字节数组(并返回)。对于情况类(实际上,对于所有Product S,其主要目的case类和元组),编码器编码只的情况下级领域被定义为类参数(在你的情况下,只有NotImportant)。你可以为你的测试用例类创建相关的编码器和检查其模式看到这一点:

case class A(s: String) { 
    var a: Int = 0 
} 

Encoders.product[A].schema.printTreeString() 
// root 
// |-- s: string (nullable = true) 

正如你所看到的 - 只有s存活,a不是架构的一部分。

有什么替代?当使用火花(真的,斯卡拉一般),你应该从可变领域避免。试造型您的数据包含所有字段为永恒不变的领域,如:

case class Ais(flag: Flag, cluster: Cluster, visited: Boolean) 

然后,“变异”这些对象,你可以使用同场的一些(或无)创建一个新的实例copy方法改变,例如:

val a = Ais(Ais.Flag.NotFlagged, Ais.Unknown, false) 
val b = a.copy(visited = true) 

这些对象将安全使用与火花(他们“幸存”序列化,是不可变的)。

+0

谢谢,这证实了我的怀疑。有没有办法使用其他编码器(如kryo)来保存可变变量状态? –