Scala case类中的def与lazy val
我有一个我定义为case类的DAO对象Scala case类中的def与lazy val,scala,lazy-evaluation,function,Scala,Lazy Evaluation,Function,我有一个我定义为case类的DAO对象 case class StudentDAO(id: Int) { def getGPA: Double = // Expensive database lookup goes here def getRank: Int = // Another expensive database operation and computation goes here def getScoreCard: File = // Expensive file loo
case class StudentDAO(id: Int) {
def getGPA: Double = // Expensive database lookup goes here
def getRank: Int = // Another expensive database operation and computation goes here
def getScoreCard: File = // Expensive file lookup goes here
}
我自然会做getGPA
和getRank
和getScoreCard
def
s而不是val
s,因为我不希望在使用它们之前计算它们
如果我将这些方法标记为lazy val
s而不是def
s,会对性能产生什么影响?我想让他们lazy val
s的原因是:我不想每次为id为“I”的学生重新计算排名
我希望这不会被标记为重复,因为下面有几个问题主要是关于差异的:
这个问题主要是针对成本高昂的操作制定方法
alazy val
的费用(CPU与内存之间的权衡),一个建议比另一个建议如何,为什么
编辑:谢谢你的评论@om nom nom。我应该更清楚我在找什么
我在这里读到:
对象的字符串表示形式将被缓存(请参见)。更准确地说,如果我将垃圾收集改为
lazy val
,而不是def
对我来说似乎非常简单,那么我将考虑垃圾收集的影响:
我不希望他们在可能被计算之前就被计算出来
用过。
[...]
我不想每次为id为“I”的学生重新计算排名
然后使用lazy val
,就是这样
def
用于每次调用的值可能更改时,通常是因为您传递了参数,val
不会更改,但会立即计算。对于“普通”引用类型(例如,文件
)的延迟val
具有在第一次计算时创建强引用的效果。因此,虽然它将避免对不变的值进行重新评估,但将计算出的值保留在内存中的成本是显而易见的
对于基本值(甚至是轻量级对象,如
文件
),这种内存开销通常不是什么问题(除非您在内存中持有大量学生
对象)。但是,对于大量引用(例如,大型数据结构),最好使用弱引用、其他缓存方法,或者只按需计算值。您希望听到什么?lazy val会让你多消耗10个字节和200个CPU周期?@om-nom-nom:不完全是。请参阅我的编辑:)因此将其设置为def
而不是lazy val
是有意义的,因为该值可能会更改?那么最好是一个def
!对垃圾收集的影响如何?请查看我的编辑。如果值可能更改,则它肯定是一个def
。一个val
将被计算一次,就这样。有意义。假设该值不会更改,并且我想使用lazy val
而不是def
,那么对GC有什么影响?它将是您实例的一个属性,除非不再引用您的StudentDAO
,否则它不会被垃圾收集。如果可以重新计算该值,但您希望保留计算值,除非GC需要内存,请查看WeakReference