Scala Case class.copy()和大型对象

Scala Case class.copy()和大型对象,scala,Scala,假设通过REST端点接收大型对象(在我的情况下为数兆字节的附件,每天数千个),并将其存储在case类中,如下所示: case class Box(largeBase64Object: String, results: List[String]) 现在,这个case类的实例在多个连续步骤(链)中处理。每个链步骤都可以通过调用box.copy(results=“foo”::box.results)来更改实例(实际上,这个示例被简化了,它实际上是一个存储每个步骤结果的无形状HList) 单个步骤可能

假设通过REST端点接收大型对象(在我的情况下为数兆字节的附件,每天数千个),并将其存储在case类中,如下所示:

case class Box(largeBase64Object: String, results: List[String])
现在,这个case类的实例在多个连续步骤(链)中处理。每个链步骤都可以通过调用
box.copy(results=“foo”::box.results)
来更改实例(实际上,这个示例被简化了,它实际上是一个存储每个步骤结果的无形状HList)

单个步骤可能是,例如病毒扫描,它会将扫描程序的结果(已感染/未感染为
布尔值
)添加到
结果
列表中

然而,这种方法总是会创建潜在大型附件的新副本。是的,垃圾收集迟早会收集过期的副本,但我仍然担心潜在的开销,因为我们谈论的是每天几GB的附件数据

另一种明显的方法是将附件存储在全局可变的
映射中,而只将引用存储在
框中。这将避免每一步复制一次附件,但完全不可变的数据结构的优良属性将消失


处理这些情况的标准方法是什么?是否有人指向反映此场景的基准点(复制与全局存储)?

不复制case类引用的对象,仅复制case类本身,所有引用都将指向与原始对象相同的对象(当然,您明确更改的对象除外)

我们不能查看copy方法的源代码,因为它是由编译器生成的,但是我们可以使用
-Xprint:typer
编译器标志来查看它生成的代码

给你的案例课

case class Box(largeBase64Object: String, results: List[String])
我们看到了生成的方法(我使用的是Scalac2.12.3)

def copy(largeBase64Object:String=largeBase64Object,结果:List[String]=results):Box=newbox(largeBase64Object,结果);
def copy$default$1:String=Box.this.largeBase64Obj
def copy$default$2:List[String]=Box.this.results;

正如我们所看到的,copy方法只是使用它传递的对象创建case类的新实例,默认情况下只直接使用case类的字段,而不进行任何形式的复制。

它不会创建附件的副本。所有副本都将引用相同的
LargeBase64对象
值。哦,真的吗?太酷了……你能帮我吗。加上这个作为答案,这样我就可以接受它可能重复的Jep,重复!实际上,我不认为“结构共享”是一个相关的概念。它只是一个浅拷贝,而不是一个深拷贝。
<synthetic> def copy(largeBase64Object: String = largeBase64Object, results: List[String] = results): Box = new Box(largeBase64Object, results);
<synthetic> def copy$default$1: String = Box.this.largeBase64Obj
<synthetic> def copy$default$2: List[String] = Box.this.results;