【问题标题】:def vs lazy val in case class案例类中的 def 与惰性 val
【发布时间】:2014-07-22 16:41:29
【问题描述】:

我有一个 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 lookup goes here
}

我自然会创建 getGPAgetRankgetScoreCard defs 而不是 vals,因为我不希望在使用它们之前计算它们。

如果我将这些方法标记为lazy vals 而不是defs,会对性能产生什么影响?我想让他们成为lazy vals 的原因是:我不想每次都为 id 为“i”的学生重新计算排名。

我希望这不会被标记为重复,因为下面有几个问题主要是关于差异的:

When to use val, def, and lazy val in Scala?

def or val or lazy val for grammar rules?

`def` vs `val` vs `lazy val` evaluation in Scala

Scala Lazy Val Question

这个问题主要针对成本(CPU 与内存之间的权衡)在为昂贵的操作创建 methodlazy val 时,有什么建议而不是其他建议以及为什么?

编辑:感谢您的评论@om-nom-nom。我应该更清楚我在寻找什么。

我在这里读到:

Use of lazy val for caching string representation

对象的字符串表示被缓存(见@Dave Griffith's answer)。更准确地说,如果我将垃圾收集设置为 lazy val 而不是 def,我正在研究垃圾收集的影响

【问题讨论】:

  • 您希望听到什么? lazy val 会多消耗 10 个字节和 200 个 CPU 周期?
  • @om-nom-nom:不完全是。请看我的编辑:)

标签: scala lazy-evaluation function


【解决方案1】:

对我来说似乎很简单:

我不希望它们在可能之前被计算出来 用过的。 [...] 我不想每次都为 ID 为“i”的学生重新计算排名。

然后使用lazy val 就可以了。

def 用于每次调用的值可能发生变化时使用,通常是因为您传递参数,val 不会改变,但会立即计算。

【讨论】:

  • 所以将其设为def 而不是lazy val 是有意义的,因为值可能会改变?那么最好是def!对垃圾回收有何影响?请查看我的编辑。
  • 如果值可能发生变化,那么肯定是defval 将被计算一次,仅此而已。
  • 有道理。说如果值不会改变,我想用lazy val而不是def,对GC有什么影响?
  • 这将是您的实例的一个属性,在您不再引用您的 StudentDAO 之前,它不会被垃圾收集。
  • 如果可以重新计算该值,但您希望保留计算的值,除非 GC 需要内存,请查看 WeakReference
【解决方案2】:

“普通”引用类型(例如,File)的 lazy val 具有在第一次评估时创建强引用的效果。因此,虽然它可以避免重新评估一个不变的值,但将计算的值保存在内存中的成本明显。

对于原始值(甚至是轻量级对象,例如File),这种内存消耗通常不是什么大问题(除非您在内存中保存了大量Student 对象)。但是,对于重引用(例如,大型数据结构),您最好使用弱引用、其他一些缓存方法,或者只是按需计算值。

【讨论】:

    猜你喜欢
    • 2021-10-17
    • 2021-03-01
    • 2019-07-18
    • 1970-01-01
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 2015-01-31
    相关资源
    最近更新 更多