Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

hashCode in case classes in Scala

People also ask

What is hashCode in Scala?

Scala String hashCode() method with example The hashCode() method is utilized to find the hash code of the stated string. Method Definition: int hashCode() Return Type: It returns an integer hash code of the string given.

Can Scala case class have methods?

Case Classes You can construct them without using new. case classes automatically have equality and nice toString methods based on the constructor arguments. case classes can have methods just like normal classes.

What is the case class in Scala?

What is Scala Case Class? A Scala Case Class is like a regular class, except it is good for modeling immutable data. It also serves useful in pattern matching, such a class has a default apply() method which handles object construction. A scala case class also has all vals, which means they are immutable.

What is the benefit of case class in Scala?

While all of these features are great benefits to functional programming, as they write in the book, Programming in Scala (Odersky, Spoon, and Venners), “the biggest advantage of case classes is that they support pattern matching.” Pattern matching is a major feature of FP languages, and Scala's case classes provide a ...


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.


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.


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.


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))
    }))
  };