具有缓存hashCode的Scala案例类
我的印象是Scala案例类的hashCode完全由其字段决定。因此,我认为缓存hashCode对于不可变的case类是安全的。具有缓存hashCode的Scala案例类
好像我错了:
case class Foo(s: String) {
override val hashCode: Int = super.hashCode()
}
val f1 = Foo("foo")
val f2 = Foo("foo")
println(f1.hashCode == f2.hashCode) // FALSE
谁能解释这是怎么回事就在这里,好吗?
附录 - 只为了比较:
case class Bar(s: String)
val b1 = Bar("bar")
val b2 = Bar("bar")
println(b1.hashCode == b2.hashCode) // TRUE
不知道有关这个价值,但是你可以内嵌的ScalaRuntime._hashCode
实现:
case class Foo(s: String) {
override val hashCode: Int = scala.util.hashing.MurmurHash3.productHash(this)
}
不知道你的意思是“缓存hasCode”,但。 .. 您已覆盖hashCode
与从Object
建立的自定义解决方案,这就是为什么你得到false
。删除这个覆盖,你会得到预期的价值。
我想记忆不可变case类的hashCode。但你现在就应该使用'override def hashCode():Int = ScalaRunTime._hashCode(this)'而不是'super.hashCode()'!这不是公共API,但...谢谢! – netzwerg
@ Rumoku的答案似乎变得什么是真正回事。当你声明case class Foo
它编译成这个:case class Foo extends AnyRef with Product with Serializable
(见scalac
的-Xprint:typer
选项)。另外,hashCode
的实现也生成如下:override def hashCode: Int = scala.runtime.ScalaRunTime._hashCode(this)
。但是,如果自己覆盖hashCode
,则不会生成此实施。关键是Product
和Serializable
都不实现hashCode
,所以当您拨打super.hashCode
时您正在执行的实现是AnyRef
/Any
/Object
的默认实现。
是的,这是一个很好的解决方案:与基于公共API的实现一样,行为好像没有被覆盖(即仅基于字段的散列),但是被记忆 - 谢谢! – netzwerg