我的印象是Scala案例类的hashCode完全由其字段决定。因此,我认为缓存hashCode对于不可变的case类是安全的。
好像我错了:
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
答案 0 :(得分:8)
不确定此值,但您可以内联ScalaRuntime._hashCode
的实现:
case class Foo(s: String) {
override val hashCode: Int = scala.util.hashing.MurmurHash3.productHash(this)
}
答案 1 :(得分:3)
不确定“缓存hasCode”是什么意思,但......
您已使用hashCode
构建的自定义解决方案覆盖Object
,这就是您获得false
的原因。删除此覆盖,您将获得预期值。
答案 2 :(得分:1)
@Rumoku的回答似乎得到了这里真正发生的事情。当您声明case class Foo
时,它会编译为:case class Foo extends AnyRef with Product with Serializable
(请参阅scalac
的{{1}}选项)。此外,还生成了-Xprint:typer
的实现,如下所示:hashCode
。但是,当您自己覆盖override def hashCode: Int = scala.runtime.ScalaRunTime._hashCode(this)
时,不会生成此实现。关键是,hashCode
和Product
都不会实现Serializable
,因此当您致电hashCode
时,您正在接收的实施是super.hashCode
/的默认实施AnyRef
/ Any
。
答案 3 :(得分:0)
toString
完全取决于其字段hashCode