Max Wong
Max Wong

Reputation: 750

How `set.contains` works in Scala?

Consider the following code:

import scala.collection.mutable

case class A(b: Int) {
  override def equals(obj: Any): Boolean = {
    println("called")
    obj match {
      case o: A => b == o.b
      case _ => false
    }
  }
}

val set = mutable.Set.empty[A]
val a1 = A(1)
set.add(a1)
println(set.contains(A(1)))
println(set.contains(A(2)))

Why the second call of set.contains doesn't print out "called"? Can someone explain how set identify two objects being equal?

Upvotes: 0

Views: 1805

Answers (1)

Tomer Shetah
Tomer Shetah

Reputation: 8529

As @LuisMiguelMejíaSuárez mentioned in the comments, A mutable Set is backed by a HashSet. It is well elaborated at What issues should be considered when overriding equals and hashCode in Java?

Whenever a.equals(b), then a.hashCode() must be same as b.hashCode().

This is because hashCode is a prior check, which when fails equals will definitely fail as well.

From What code is generated for an equals/hashCode method of a case class? we can conclude that for case classes hashCode and equals are overridden for case classes, using productPrefix which means the first set of elements in the case class. For example, if we have:

case class c(a: A)(b: B)

The hashCode and equals will be calculated only based on a. In your case, the hasCode method is calculated based on gender, which is different for Person(1) and Person(2). Therefore there is no need to check equals, which suppose to fail as well.

A tip from What issues should be considered when overriding equals and hashCode in Java?

In practice:

If you override one, then you should override the other.

Use the same set of fields that you use to compute equals() to compute hashCode().

Upvotes: 2

Related Questions