Scala:为什么可变Map和不可变Map在同一个自定义类实例上有不同
我的
Scala版本是2.11.8,Java版本是1.8.0_77.
我有一个自定义类V扩展Ordered [V].我定义了自定义比较和等于.我希望V实例具有>,<,> =,< =运算符,并且当它们的某些特定属性相等时可以被认为是相等的. 这是从我的项目中提取的简化代码: class V(val value: Int,val score: Int = 0) extends Ordered[V] { def compare(that: V): Int = this.score compare that.score override def equals(that: Any): Boolean = that match { case that: V => this.value == that.value case _ => false } } val a = new V(1,2) val b = new V(1,3) // return true because a.value == b.value a == b 奇怪的是: import collection.mutable.ArrayBuffer val mm = collection.mutable.Map(a -> ArrayBuffer(0,1),b -> ArrayBuffer(2,3,4)) val im = collection.immutable.Map(a -> ArrayBuffer(0,4)) // return scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() mm.getOrElse(new V(1,0),ArrayBuffer()) // return scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2,4) im.getOrElse(new V(1,ArrayBuffer()) 为什么immutable.Map和mutable.Map的结果不同? 但是当我为V定义hashCode时: class V(val value: Int,val score: Int = 0) extends Ordered[V] { def compare(that: V): Int = this.score compare that.score override def hashCode: Int = value // new method here! override def equals(that: Any): Boolean = that match { case that: V => this.value == that.value case _ => false } } val a = new V(1,3) a == b // true 而这一次,结果是一样的: val mm = collection.mutable.Map(a -> ArrayBuffer(0,4)) // both return scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2,4) mm.getOrElse(new V(1,ArrayBuffer()) im.getOrElse(new V(1,ArrayBuffer()) 为什么hashCode定义会影响自定义类实例上的可变Map的结果? 解决方法
immutable.Map具有最多4个键值对的自定义实现(Map1,….,Map4).这些自定义实现的get操作不使用内部存储桶数组来映射到实际存储值的对象数组,它只是将键值对存储为字段. 例如,这是由getOrElse调用的Map1.get: class Map1[A,+B](key1: A,value1: B) extends AbstractMap[A,B] with Map[A,B] with Serializable { def get(key: A): Option[B] = if (key == key1) Some(value1) else None 相反,mutable.Map是一个mutable.HashMap的后盾,它使用一个桶来查找对象hashcode,而hashcode又指向对象数组中的值.这些桶中的对象由其哈希码存储.由于您的对象没有实现自定义哈希码方法,因此它从Any(Object)派生它的哈希码.因此,可变映射无法在这些存储桶中找到值,因为自定义实现中的相等值不具有相等的哈希码. 实现自定义哈希码方法后,它遵循所有相等实例应该产生相同哈希码的规则,HashMap能够找到存储对象的正确存储桶,并在两个对象上调用equals,看它们是否相等. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |