函数转换对输入参数的副作用

时间:2016-09-29 12:20:18

标签: scala apache-spark

我有这样的事情:

object MyObject {
    var element1 /**/
    var element2 /**/
    var myOtherObject: OtherObject = new OtherObject
}

object MyOtherObject {
    var something1 /**/
    var something2 /**/
    var myList: List[T] = List()
}

def myUpdateFunction(iMyObject: MyObject) : SomeObject = {
    var myCopiedObject = iMyObject

    myCopiedObject.myList.dropRight
    /*checkpoint*/

    val myAwesomeOtherObject = new MyOtherObject
    /*perform multiple tasks to update myAwesomeOtherObject members*/

    myAwesomeOtherObject
}

当我在"检查点"上检查myUpdateFunction执行时注释,我观察我的myCopiedObject.myList已成功转换,但我的iMyObject也有,即。 iMyObject.myList被一个人截断了。

我不明白这是怎么发生的。

任何线索,任何人?

顺便说一下,我正在使用spark

2 个答案:

答案 0 :(得分:2)

之所以发生这种情况,是因为您只是将同一个对象分配给另一个引用。 Exception in thread "main" java.io.IOException: mkdir of C:/Users/Manuel%20Mourato/AppData/Local/Temp/temporary-891579db-0442-4e1c-8642-d41c7885ab26/offsets failed at org.apache.hadoop.fs.FileSystem.primitiveMkdir(FileSystem.java:1065) at org.apache.hadoop.fs.DelegateToFileSystem.mkdir(DelegateToFileSystem.java:176) at org.apache.hadoop.fs.FilterFs.mkdir(FilterFs.java:197) at org.apache.hadoop.fs.FileContext$4.next(FileContext.java:730) at org.apache.hadoop.fs.FileContext$4.next(FileContext.java:726) at org.apache.hadoop.fs.FSLinkResolver.resolve(FSLinkResolver.java:90) at org.apache.hadoop.fs.FileContext.mkdir(FileContext.java:733) at org.apache.spark.sql.execution.streaming.HDFSMetadataLog$FileContextManager.mkdirs(HDFSMetadataLog.scala:281) at org.apache.spark.sql.execution.streaming.HDFSMetadataLog.<init>(HDFSMetadataLog.scala:57) at org.apache.spark.sql.execution.streaming.StreamExecution.<init>(StreamExecution.scala:131) at org.apache.spark.sql.streaming.StreamingQueryManager.startQuery(StreamingQueryManager.scala:251) at org.apache.spark.sql.streaming.DataStreamWriter.start(DataStreamWriter.scala:287) at org.apache.spark.sql.streaming.DataStreamWriter.start(DataStreamWriter.scala:231) 不是您对象的副本。您应该编写一个方法,使用与myCopiedObject相同的值创建MyObject的新实例。

答案 1 :(得分:2)

var myCopiedObject = iMyObject

上面的代码不会创建对象的副本。您基本上是指同一个对象,但使用不同的参考。

使用case class并使用copy方法创建包含所需更改的副本

case class Something(list: List[Int])

val sthing = Something(List(1, 2))
val copy = sthing.copy(list = sthing.list.take(1)) //creating changed copy using copy method
相关问题