我有一个表示销售订单的类:
class SalesOrder(val f01:String, val f02:Int, ..., f50:Date)
fXX字段有多种类型。我面临着为我的订单创建审计跟踪的问题。给定类的两个实例,我必须确定哪些字段发生了更改。我想出了以下几点:
class SalesOrder(val f01:String, val f02:Int, ..., val f50:Date){
def auditDifferences(that:SalesOrder): List[String] = {
def diff[A](fieldName:String, getField: SalesOrder => A) =
if(getField(this) != getField(that)) Some(fieldName) else None
val diffList = diff("f01", _.f01) :: diff("f02", _.f02) :: ...
:: diff("f50", _.f50) :: Nil
diffList.flatten
}
}我想知道编译器如何处理所有的_.fXX函数:它们是只实例化一次(静态地),并且可以被我的类的所有实例共享,还是每次我创建我的类的实例时都实例化它们?
我担心的是,由于我将使用大量SalesOrder实例,因此可能会产生大量垃圾。我应该使用不同的方法吗?
发布于 2013-07-01 07:35:20
解决这个问题的一种干净的方法是使用标准库的Ordering type class。例如:
class SalesOrder(val f01: String, val f02: Int, val f03: Char) {
def diff(that: SalesOrder) = SalesOrder.fieldOrderings.collect {
case (name, ord) if !ord.equiv(this, that) => name
}
}
object SalesOrder {
val fieldOrderings: List[(String, Ordering[SalesOrder])] = List(
"f01" -> Ordering.by(_.f01),
"f02" -> Ordering.by(_.f02),
"f03" -> Ordering.by(_.f03)
)
}然后:
scala> val orderA = new SalesOrder("a", 1, 'a')
orderA: SalesOrder = SalesOrder@5827384f
scala> val orderB = new SalesOrder("b", 1, 'b')
orderB: SalesOrder = SalesOrder@3bf2e1c7
scala> orderA diff orderB
res0: List[String] = List(f01, f03)几乎可以肯定的是,您不需要担心原始公式的性能,但这个版本(可以说)更好,因为一些无关的原因。
发布于 2013-07-01 04:29:36
是的,这会创建50个短暂的函数。我不认为您应该担心,除非您有明显的证据表明这会导致您的情况下的性能问题。
但是我会定义一个将SalesOrder转换为Map[String, Any]的方法,然后您就可以拥有
trait SalesOrder {
def fields: Map[String, Any]
}
def diff(a: SalesOrder, b: SalesOrder): Iterable[String] = {
val af = a.fields
val bf = b.fields
af.collect { case (key, value) if bf(key) != value => key }
}如果字段名确实只是递增的数字,那么您可以简化
trait SalesOrder {
def fields: Iterable[Any]
}
def diff(a: SalesOrder, b: SalesOrder): Iterable[String] =
(a.fields zip b.fields).zipWithIndex.collect {
case ((av, bv), idx) if av != bv => f"f${idx + 1}%02d"
}https://stackoverflow.com/questions/17394302
复制相似问题