我有:
val rdd1: RDD[myClass]
它已被初始化,我在调试时检查了所有成员都有其默认值
如果我这样做
rdd1.foreach(x=>x.modifier())
其中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())
答案 0 :(得分:8)
RDD是不可变的,在它包含的对象上调用变异方法不会产生任何影响。
获得所需结果的方法是生成<div id="first-result"></div>
<div id="second-result"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
的新副本,而不是修改实例:
MyClass
现在你仍然无法更新rdd1,但你可以获得将包含更新实例的rdd2:
case class MyClass(id:String, avgsession: Long) {
def modifier(a: Int):MyClass =
this.copy(avgsession = this.avgsession + a)
}
答案 1 :(得分:1)
此问题的答案与此处最初接受的答案相比略有细微差别。原始答案仅对于未缓存在内存中的数据是正确的。缓存在内存中的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是从源重新计算或从磁盘上的序列化副本读取,则它将始终重置回原始对象,并且看起来是不可变的,但如果不是从序列化形式加载,则该突变实际上会保留。
答案 2 :(得分:0)
我观察到,在使用spark / yarn运行时调用RDD.persist之后,像你这样的代码会起作用。这可能是不受支持/意外的行为,你应该避免它 - 但这是一个可能有助于紧急的解决方法。我正在运行1.5.0版本。
答案 3 :(得分:0)
对象是不可变的。通过使用map,您可以遍历rdd并返回一个新的。
val rdd2 = rdd1.map(x=>x.modifier())