Ale*_*lex 1 hash scala hashset
我正在使用 Scala 2.11。
我有一个案例类Dimension,并创建了它的 3 个实例。当我将它们放入HashSet时,我惊讶地发现只有 1 被正确添加。然后我尝试调试,发现它们有相同的 hashCode。
我是 Scala 新手,但在 Java 方面有很多经验。我想知道为什么它们都具有相同的 hashCode,即使它们具有不同的字段,以及 Scala 案例类中 hashCode 方法的默认实现是什么?HashSet/HashMap 在 Scala 中如何工作?
这是我的代码示例。
object Echo {
def main( args:Array[String] ):Unit = {
var d1 = new Dimension
d1.name = "d1"
d1.dimensionId = "1"
println("d1:" + d1.hashCode()) // d1, d2, d3 have the same hashCode
var d2 = new Dimension
d2.name = "d2"
d2.dimensionId = "2"
println("d2:" + d2.hashCode())
var d3 = new Dimension
d3.name = "d3"
d3.dimensionId = "3"
println("d3:" + d3.hashCode())
var l = List(d1, d2, d3)
val categories = mutable.HashSet.empty[Dimension]
l.foreach(md => {
categories += md
})
println(categories.size) // size is 1
}
}
case class Dimension() {
var dimensionId: String = _
var name: String = _
}
Run Code Online (Sandbox Code Playgroud)
引用规范:
每个案例类都会隐式覆盖类 scala.AnyRef 的某些方法定义,除非案例类本身已经给出了相同方法的定义,或者在案例类的某个与 AnyRef 不同的基类中给出了相同方法的具体定义。尤其:
方法
equals: (Any)Boolean是结构相等,其中如果两个实例都属于所讨论的案例类并且它们具有相等(相对于 equals)构造函数参数(仅限于类的元素,即第一个参数部分),则它们相等。方法
hashCode: Int计算哈希码。如果数据结构成员的 hashCode 方法将相等(相对于 equals)值映射到相等的哈希码,则案例类 hashCode 方法也会这样做。
由于构造函数的参数列表是空的,每个参数列表都是Dimension空equals的Dimension,因此它们hashCode也必须相同。
只是不要将案例类与那些奇怪的未初始化的混合在一起var,或者至少要更小心地这样做。
scala 中的 HashCode 仅考虑案例类构造函数中的属性。
如果您以更实用和更灵活的方式定义案例类(例如确保不变性),则行为将是预期的:
定义
case class Dimension(dimensionId: String, name: String)
val d1 = Dimension("1", "d1")
val d2 = Dimension("2", "d2")
Run Code Online (Sandbox Code Playgroud)
结果
scala> println("d1:" + d1.hashCode())
d1:732406741
scala> println("d2:" + d2.hashCode())
d2:952021182
Run Code Online (Sandbox Code Playgroud)
您可以在这个很棒的答案中找到 hashcode 方法生成的代码