gpt4 book ai didi

Scala:为什么可变 Map 和不可变 Map 在与键相同的自定义类实例上有不同的结果?

转载 作者:行者123 更新时间:2023-12-05 00:55:03 25 4
gpt4 key购买 nike

我的 Scala 版本是 2.11.8 Java 版本是 1.8.0_77 .

我有一个自定义类 V扩展 Ordered[V] .我定义了自定义 compareequals .我要 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, 1), b -> ArrayBuffer(2, 3, 4))

// return scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
mm.getOrElse(new V(1, 0), ArrayBuffer())

// return scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 3, 4)
im.getOrElse(new V(1, 0), ArrayBuffer())

为什么 immutable.Map的结果和 mutable.Map是不同的?

但是当我定义 hashCodeV :
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, 2)
val b = new V(1, 3)

a == b // true

而这一次,结果是一样的:
val mm = collection.mutable.Map(a -> ArrayBuffer(0, 1), b -> ArrayBuffer(2, 3, 4))
val im = collection.immutable.Map(a -> ArrayBuffer(0, 1), b -> ArrayBuffer(2, 3, 4))

// both return scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 3, 4)
mm.getOrElse(new V(1, 0), ArrayBuffer())
im.getOrElse(new V(1, 0), ArrayBuffer())

为什么 hashCode定义会影响自定义类实例上可变 Map 的结果作为键吗?

最佳答案

Why does hashCode definition affect the result of mutable Map on custom class instance as key


immutable.Map具有最多 4 个键值对的自定义实现( Map1 , ...., Map4 )。 get这些自定义实现的操作不使用映射到实际存储值的对象数组的哈希码的内部存储桶数组,它只是将键值对存储为字段。

例如,这里是 Map1.getgetOrElse 调用:
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 支持的它使用一个桶来查找对象哈希码,它又指向对象数组中的值。这些存储桶中的对象由它们的哈希码存储。由于您的对象没有实现自定义哈希码方法,它从 Any 派生它的哈希码。 ( Object )。因此,可变映射无法在这些桶中找到值,因为自定义实现中的相等值没有相等的哈希码。

一旦你实现了一个自定义的 hashcode 方法,并且它遵守所有相等的实例应该产生相同的 hashcode 的规则, HashMap能够找到存储对象的正确存储桶并调用 equals在两个对象上,查看它们是否相等。

关于Scala:为什么可变 Map 和不可变 Map 在与键相同的自定义类实例上有不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39011254/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com