簡體   English   中英

修改火花中對象的RDD(scala)

[英]modifying RDD of object in spark (scala)

我有:

val rdd1: RDD[myClass]

它已被初始化,我在調試時檢查所有成員都有他們的默認值

如果我做

rdd1.foreach(x=>x.modifier())

其中修飾符是 myClass 的成員函數,它修改了一些成員變量

執行此操作后,如果我檢查 RDD 中的值,它們尚未被修改。

有人可以解釋這里發生了什么嗎? 是否可以確保在 RDD 中修改值?

編輯:

class myClass(var id:String,var sessions: Buffer[Long],var avgsession: Long)  {
    def calcAvg(){
   // calculate avg by summing over sessions and dividing by legnth
   // Store this average in avgsession
    }
}

如果我這樣做,則 avgsession 屬性不會更新

myrdd.foreach(x=>x.calcAvg())

RDD 是不可變的,對它所包含的對象調用變異方法不會有任何影響。

獲得你想要的結果的方法是生成MyClass新副本而不是修改實例:

case class MyClass(id:String, avgsession: Long) {
    def modifier(a: Int):MyClass = 
       this.copy(avgsession = this.avgsession + a) 
}

現在您仍然無法更新 rdd1,但您可以獲得包含更新實例的 rdd2:

rdd2 = rdd1.map (_.modifier(18) ) 

這個問題的答案比這里最初接受的答案要微妙得多。 原始答案僅對於未緩存在內存中的數據是正確的。 緩存在內存中的 RDD 數據也可以在內存中進行變異,即使 RDD 被認為是不可變的,變異仍將保留。 考慮以下示例:

val rdd = sc.parallelize(Seq(new mutable.HashSet[Int]()))
rdd.foreach(_+=1)
rdd.collect.foreach(println)

如果您運行該示例,您將獲得Set()作為結果,就像原始答案狀態一樣。

但是,如果您要使用緩存調用運行完全相同的內容:

val rdd = sc.parallelize(Seq(new mutable.HashSet[Int]()))
rdd.cache
rdd.foreach(_+=1)
rdd.collect.foreach(println)

現在結果將打印為Set(1) 所以這取決於數據是否被緩存在內存中。 如果 spark 從源重新計算或從磁盤上的序列化副本讀取,那么它總是會重置回原始對象並且看起來是不可變的,但是如果它不是從序列化形式加載,那么突變實際上會保持不變。

對象是不可變的。 通過使用 map,您可以遍歷 rdd 並返回一個新的。

val rdd2 = rdd1.map(x=>x.modifier())

我觀察到像你這樣的代碼在 spark/yarn 中運行時調用 RDD.persist 后可以工作。 這可能是不受支持/意外的行為,您應該避免它 - 但它是一種可能有助於解決問題的解決方法。 我正在運行 1.5.0 版。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM