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

时间:2015-09-08 14:38:04

标签: java scala hash hashmap

我有两个问题:

  1. 为什么HashMap使用密钥的内存地址作为标识符 对于地图条目,即桶。据我了解,只要我 覆盖hashCode(),密钥的哈希码将用作存储桶 而不是ID。

  2. 为什么HashMap会在注释变异时更新 以下代码:

  3. 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
        }
      }
    }
    

1 个答案:

答案 0 :(得分:7)

  

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

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

如果您想知道为什么密钥看起来像oo.Point2@20,那是因为您没有覆盖toString()类中的Point

  

当密钥变异

时,为什么HashMap会更新

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

如果密钥对象发生变化,使其HashMap方法返回不同的值(因为该条目可能突然出现在错误的存储桶中),这会弄乱您的hashCode()

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