Scala 案例类中的 hashCode
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5866720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
hashCode in case classes in Scala
提问by Mirko Stocker
I've read that Scala'a case classconstruct automatically generates a fitting equalsand hashCodeimplementation. What does exactly the generated code look like?
我读过 Scala'acase class构造会自动生成拟合equals和hashCode实现。生成的代码到底长什么样?
回答by Mirko Stocker
As my professor used to say, only the code tells the truth! So just take a look at the code that is generated for:
正如我的教授曾经说过的,只有代码才能说真话!所以只需看看为以下项目生成的代码:
case class A(i: Int, s: String)
We can instruct the Scala compiler to show us the generated code after the different phases, here after the typechecker:
我们可以指示 Scala 编译器在不同阶段之后向我们展示生成的代码,这里是在类型检查器之后:
% scalac -Xprint:typer test.scala
[[syntax trees at end of typer]]// Scala source: test.scala
package <empty> {
@serializable case class A extends java.lang.Object with ScalaObject with Product {
..
override def hashCode(): Int = ScalaRunTime.this._hashCode(A.this);
...
override def equals(x: Any): Boolean = A.this.eq(x).||(x match {
case (i: Int,s: String)A((i @ _), (s @ _)) if i.==(i).&&(s.==(s)) => x.asInstanceOf[A].canEqual(A.this)
case _ => false
});
override def canEqual(x: Any): Boolean = x.$isInstanceOf[A]()
};
}
So you can see that the calculation of the hash code is delegated to ScalaRunTime._hashCodeand the equality depends on the equality of the case class' members.
所以你可以看到哈希码的计算委托给ScalaRunTime._hashCode并且相等性取决于案例类成员的相等性。
回答by sepp2k
The generated hashCodejust calls scala.runtime.ScalaRunTime._hashCode, which is defined as:
生成的hashCode只是调用scala.runtime.ScalaRunTime._hashCode,其定义为:
def _hashCode(x: Product): Int = {
val arr = x.productArity
var code = arr
var i = 0
while (i < arr) {
val elem = x.productElement(i)
code = code * 41 + (if (elem == null) 0 else elem.hashCode())
i += 1
}
code
}
So what you get is elem1 * 41**n + elem2 * 41**(n-1) .. elemn * 1, where nis the arity of your case class and elemiare the members of that case class.
所以你得到的是elem1 * 41**n + elem2 * 41**(n-1) .. elemn * 1,n你的案例类的数量在哪里,并且是该案例类elemi的成员。
回答by Alexander Poluektov
Please be aware that the previous answers on this question are a bit outdated on the hashCode part.
请注意,之前关于这个问题的答案在 hashCode 部分有点过时。
As of scala 2.9 hashCodefor case classes uses MurmurHash: link.
从 Scala 2.9 开始hashCode,案例类使用MurmurHash: link。
MurmurHash produces good avalanche effect, good distribution and is CPU friendly.
MurmurHash产生良好的雪崩效果,良好的分布并且对 CPU 友好。
回答by Pete
Looks like things have changed; using Mirko's example case class A(i: Int, s: String)I get:
看起来事情已经发生了变化;使用 Mirko 的例子,case class A(i: Int, s: String)我得到:
override <synthetic> def hashCode(): Int = {
<synthetic> var acc: Int = -889275714;
acc = scala.runtime.Statics.mix(acc, i);
acc = scala.runtime.Statics.mix(acc, scala.runtime.Statics.anyHash(s));
scala.runtime.Statics.finalizeHash(acc, 2)
};
and
和
override <synthetic> def equals(x: Any): Boolean = A.this.eq(x.asInstanceOf[Object]).||(x match {
case (_: A) => true
case _ => false
}.&&({
<synthetic> val A: A = x.asInstanceOf[A];
A.this.i.==(A.i).&&(A.this.s.==(A.s)).&&(A.canEqual(A.this))
}))
};

