I've read that Scala'a case class
construct automatically generates a fitting equals
and hashCode
implementation. What does exactly the generated code look like?
-
1possible duplicate of [What code is generated for an equals/hashCode method of a case class?](http://stackoverflow.com/questions/4526706/what-code-is-generated-for-an-equals-hashcode-method-of-a-case-class) – Suma Mar 13 '15 at 15:18
4 Answers
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:
% 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$1: Any): Boolean = A.this.eq(x$1).||(x$1 match {
case (i: Int,s: String)A((i$1 @ _), (s$1 @ _)) if i$1.==(i).&&(s$1.==(s)) => x$1.asInstanceOf[A].canEqual(A.this)
case _ => false
});
override def canEqual(x$1: Any): Boolean = x$1.$isInstanceOf[A]()
};
}
So you can see that the calculation of the hash code is delegated to ScalaRunTime._hashCode and the equality depends on the equality of the case class' members.

- 2,232
- 16
- 22
-
6This not only explains it well, but taught me about `-Xprint:typer`. Thanks a lot! The only thing I'm confused about is what does `ScalaRunTime.this` mean? Why not simply `ScalaRunTime._hashCode`? – May 03 '11 at 08:44
-
The `ClassName.this` syntax is usually used to access an outer `this` from within an inner class (that's the same as in Java). Not sure why it's printed here, maybe it's just the way the code is pretty printed by the compiler. But that's just a guess, anyone else? – Mirko Stocker May 03 '11 at 08:52
The generated hashCode
just calls scala.runtime.ScalaRunTime._hashCode
, which is defined as:
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 n
is the arity of your case class and elemi
are the members of that case class.

- 363,768
- 54
- 674
- 675
-
Thanks for the clear answer. Now I don't know whether I should accept your answer or Mirko's answer, from which I also learnt the handy `-Xprint:typer` trick... – May 03 '11 at 08:46
-
Please be aware that the previous answers on this question are a bit outdated on the hashCode part.
As of scala 2.9 hashCode
for case classes uses MurmurHash
: link.
MurmurHash produces good avalanche effect, good distribution and is CPU friendly.

- 1
- 1

- 7,844
- 1
- 28
- 32
Looks like things have changed; using Mirko's example case class A(i: Int, s: String)
I get:
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$1: Any): Boolean = A.this.eq(x$1.asInstanceOf[Object]).||(x$1 match {
case (_: A) => true
case _ => false
}.&&({
<synthetic> val A$1: A = x$1.asInstanceOf[A];
A.this.i.==(A$1.i).&&(A.this.s.==(A$1.s)).&&(A$1.canEqual(A.this))
}))
};

- 16,534
- 9
- 40
- 54
-
It looks to me like `scala.runtime.ScalaRunTime._hashCode` still works, though, and based on the comments in the code, I'd expect it to produce the same result. ScalaRuntime delegates to MurmerHash3, which contains the comment: "Case objects have the hashCode inlined directly into the synthetic hashCode method, but this method should still give a correct result if passed a case object." – mbbush Apr 23 '18 at 18:44