当对象变异时,HashMap会自动更新

Luo*_*inh 1 java hash scala hashmap

我有两个问题:

  1. 为什么HashMap使用密钥的内存地址作为映射条目的标识符,即桶.据我所知,只要我覆盖hashCode(),密钥的哈希码将用作桶ID.

  2. 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
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Jes*_*per 7

为什么HashMap使用密钥的内存地址作为映射条目的标识符

它没有.它使用密钥的哈希码.(为什么你认为它使用内存地址?).

如果你想知道为什么键是这样的oo.Point2@20,那是因为你没有toString()在课堂上覆盖Point.

为什么在密钥变异时HashMap会更新

因为HashMap不会复制您用作键的对象; 它只存储对关键对象的引用.如果在将密钥放入后修改密钥HashMap,则HashMap还会看到更改.

HashMap如果密钥对象以一种方式更改其hashCode()方式将返回不同的值(因为该条目可能突然出现在错误的桶中),这将使您陷入困境.

不要修改在a中用作键的对象HashMap,因为这会导致奇怪的问题(例如,对象可能看起来像是从地图中消失了).在a中用作键的对象HashMap应该是不可变的.

  • 实际上要求密钥是不可变的太严格了.要求密钥的*身份*不要改变就足够了.不管怎么说,答案很好. (2认同)