具有缓存hashCode的Scala案例类

时间:2016-09-29 16:10:23

标签: scala

我的印象是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

4 个答案:

答案 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)时,不会生成此实现。关键是,hashCodeProduct都不会实现Serializable,因此当您致电hashCode时,您正在接收的实施是super.hashCode /的默认实施AnyRef / Any

答案 3 :(得分:0)

案例类实例的

toString完全取决于其字段hashCode