【发布时间】:2021-01-19 22:03:43
【问题描述】:
考虑以下代码:
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 如何识别两个相等的对象吗?
【问题讨论】:
-
可变的
Set由HashSet支持,因此它首先调用hashcode来识别某个桶,然后使用equals来比较桶的元素。这就是为什么hashcode和equals必须始终保持一致,否则你会为这样的错误打开大门。 - 顺便说一句,在实践中,永远不要覆盖 case 类 的equals,如果您想要自定义等价性,请改用普通类。 -
@LuisMiguelMejíaSuárez 太好了!你能解释一下 Scala 中
hashCode的原始实现是什么,如果我只想查看一个类的属性子集来确定两个实例是否相等,我该如何覆盖它。 -
搜索 "Effective Java hashcode and equals" - 请使用普通类,除非您希望为您的代码的未来合作者感到兴奋。另外,我建议选择不同的设计,例如将不属于相等性的字段移动到第二个参数列表或具有两个案例类。
-
@LuisMiguelMejíaSuárez 太好了!这完全解决了我的问题。您介意写一个简短的答案,以便我接受并结束这个问题吗?谢谢!
标签: scala set equals hashcode case-class