2017-05-09 37 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)來保存可變變量狀態? –