`set.contains` 在 Scala 中是如何工作的?

问题描述

考虑以下代码

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

为什么 set.contains 的第二次调用没有打印出“已调用”?有人能解释一下 set 如何识别两个相等的对象吗?

解决方法

正如@LuisMiguelMejíaSuárez 在评论中提到的,可变 SetHashSet 支持。它在 What issues should be considered when overriding equals and hashCode in Java?

中得到了很好的阐述

当 a.equals(b) 时,a.hashCode() 必须与 b.hashCode() 相同。

这是因为 hashCode 是先验检查,失败时 equals 肯定也会失败。

What code is generated for an equals/hashCode method of a case class? 我们可以得出结论,对于案例类,hashCodeequals 被案例类覆盖,使用 productPrefix 表示案例类中的第一组元素.例如,如果我们有:

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

hashCodeequals 将仅基于 a 计算。在您的情况下,hasCode 方法是基于 gender 计算的,这对于 Person(1)Person(2) 是不同的。因此没有必要检查 equals,它假定也会失败。

来自What issues should be considered when overriding equals and hashCode in Java?的提示

在实践中:

如果你覆盖了一个,那么你应该覆盖另一个。

使用与计算 equals() 相同的一组字段来计算 hashCode()。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...