深度Scala在mutability
和上呈现此代码equality
.
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 } } }
然后,它执行评估.
scala> val x = new Point2(1,1) x: Point2 = Point2@20 scala> val y = new Point2(1,2) y: Point2 = Point2@21 scala> val z = new Point2(1,1) z: Point2 = Point2@20
接下来,HashMap
创建一个.
scala> val map = HashMap(x -> "HAI", y -> "WORLD") map: scala.collection.immutable.HashMap[Point2,java.lang.String] = Map((Point2@21,WORLD), (Point2@20,HAI)) scala> x.move(1,1) scala> map(y) res9: java.lang.String = WORLD
据我所知,自从发生变异后map(x)
将会返回.由于突变,重新计算了hashCode .结果,当检查是否在,没有地图的匹配是新的.NoSuchElementException
x
x
x.move(1,1
x
map
hashCode
x
hashCode
scala> map(x) java.util.NoSuchElementException: key not found: Point2@40 ...
由于z
equals(value)最初插入x
的HashMap
,以及hashCode
为什么抛出异常?
scala> map(z) java.util.NoSuchElementException: key not found: Point2@20
编辑在我看来,这个例子显示了命令式编程的复杂性(坏).
因为Map仍然用于x
测试相等性.
这是发生的事情:
你使用x
键作为键插入地图中,此时的hashCode是#x.大.
你改变了一些值x
,#x现在消失了,新的hashCode是#x'.
您尝试查找x
与地图关联的值.地图获取hashCode:#x'.它在地图中不存在(因为在插入时它是#x).
你z
用x
最初的相同值创建.
你查找与之关联的值z
.地图发现的的hashCode值z
(因为它是#X),但随后调用equals
上z
和x
(同一个实例,你使用过程中的第一步,插入值).false
你搬家后就得到了x
!
映射保留对密钥实例的引用,并使用它来测试equals
何时get
,但它从不重新计算hashCode.