我有两个问题:
为什么HashMap
使用密钥的内存地址作为标识符
对于地图条目,即桶。据我了解,只要我
覆盖hashCode()
,密钥的哈希码将用作存储桶
而不是ID。
为什么HashMap
会在注释变异时更新
以下代码:
object Equals {
def main(args: Array[String]) {
val pointX = new Point2(1, 1)
val pointY = new Point2(2, 1)
val pointZ = new Point2(4, 4)
val map = HashMap(pointX -> "X", pointY -> "Y")
println(s"Map before: $map")
//Map before: Map(oo.Point2@20 -> X, oo.Point2@3f -> Y)
pointX.move(3, 3)
println(s"Map after: $map")
//Map after: Map(oo.Point2@80 -> X, oo.Point2@3f -> Y)
println(map(pointZ))
}
}
class Point2(var x: Int, var y: Int) extends Equals {
def move(mx: Int, my: Int): Unit = {
x = x + mx
y = y + my
}
override def hashCode(): Int = y + (31 * x)
def canEqual(that: Any): Boolean = that match {
case p: Point2 => true
case _ => false
}
override def equals(that: Any): Boolean = {
def strictEquals(other: Point2) =
this.x == other.x && this.y == other.y
that match {
case a: AnyRef if this eq a => true
case p: Point2 => (p canEqual this) && strictEquals(p)
case _ => false
}
}
}
答案 0 :(得分:7)
为什么HashMap使用密钥的内存地址作为映射条目的标识符
它没有。它使用密钥的哈希码。 (为什么你认为它使用内存地址?)。
如果您想知道为什么密钥看起来像oo.Point2@20
,那是因为您没有覆盖toString()
类中的Point
。
当密钥变异
时,为什么HashMap会更新
因为HashMap
没有复制您用作键的对象;它只存储对关键对象的引用。如果您在将密钥放入HashMap
后修改密钥,则HashMap
也会看到更改。
如果密钥对象发生变化,使其HashMap
方法返回不同的值(因为该条目可能突然出现在错误的存储桶中),这会弄乱您的hashCode()
。
不要修改用作HashMap
中键的对象,因为这会导致奇怪的问题(例如,对象可能看起来像是从地图中消失了)。在HashMap
中用作键的对象应该是不可变的。