Java HashMap在对象发生变化时自动更新
我有两个问题:Java HashMap在对象发生变化时自动更新,java,scala,hash,hashmap,Java,Scala,Hash,Hashmap,我有两个问题: 为什么HashMap使用密钥的内存地址作为标识符 用于地图输入,即bucket。据我所知,只要我 重写hashCode(),密钥的哈希代码将用作bucket 而不是我 为什么当密钥如中所述发生变化时,HashMap会得到更新 代码如下: 为什么HashMap使用键的内存地址作为映射项的标识符 没有。它使用密钥的哈希代码。(您认为它为什么使用内存地址?) 如果您想知道为什么键看起来像oo。Point2@20,这是因为您没有在类点中重写toString() 为什么当密钥发生变化时H
HashMap
使用密钥的内存地址作为标识符
用于地图输入,即bucket。据我所知,只要我
重写hashCode()
,密钥的哈希代码将用作bucket
而不是我HashMap
会得到更新
代码如下:为什么HashMap使用键的内存地址作为映射项的标识符 没有。它使用密钥的哈希代码。(您认为它为什么使用内存地址?) 如果您想知道为什么键看起来像
oo。Point2@20
,这是因为您没有在类点中重写toString()
为什么当密钥发生变化时HashMap会得到更新
因为HashMap
不会复制用作键的对象;它只存储对键对象的引用。如果在将键放入HashMap
后修改该键,则HashMap
也会看到更改
如果键对象的更改方式使其hashCode()
方法返回不同的值(因为条目可能突然位于错误的存储桶中),则这将打乱您的HashMap
不要修改在HashMap
中用作键的对象,因为这会导致奇怪的问题(例如,对象可能会从映射中消失)。在HashMap
中用作键的对象应该是不可变的
为什么HashMap使用键的内存地址作为映射项的标识符
没有。它使用密钥的哈希代码。(您认为它为什么使用内存地址?)
如果您想知道为什么键看起来像oo。Point2@20
,这是因为您没有在类点中重写toString()
为什么当密钥发生变化时HashMap会得到更新
因为HashMap
不会复制用作键的对象;它只存储对键对象的引用。如果在将键放入HashMap
后修改该键,则HashMap
也会看到更改
如果键对象的更改方式使其hashCode()
方法返回不同的值(因为条目可能突然位于错误的存储桶中),则这将打乱您的HashMap
不要修改在HashMap
中用作键的对象,因为这会导致奇怪的问题(例如,对象可能会从映射中消失)。在HashMap
中用作键的对象应该是不可变的。不仅仅是HashMap。。这就是java的工作原理。。那也是出于某种原因。。如果你想让你的类不可变,那就让它不可变。它不仅仅是HashMap。。这就是java的工作原理。。那也是出于某种原因。。如果你想让你的类不可变,就让它不可变。实际上要求键不可变太严格了。要求密钥的标识不改变就足够了。不管怎么说,答案很好。如果钥匙的标识很重要的话,IdentityHashMap
将是一个不错的选择。然后你可以自由地改变你的键。@Federicoperaltachaffner据我所知,参考值是一个对象的标识。将同一性视为参考值的同义词,那么这个名称就完全有意义了。@Durandal好的,我理解你的意思。我的意思是关于equals()
合同的身份,即,如果您有一个个人
对象,该对象具有社会安全号码
、姓名
和姓氏
字段,那么关于equals()
的身份将仅由社会安全号码
字段定义,因为它在所有人中都是独一无二的。但实际上,这是平等而不是身份。我的错。@Luongbalin bucket更像是一个成对的链表:[(键1,值1),(键2,值2),…]而不是[(hashCode(键1,值1),(hashCode(键2,值2),…]),实际上要求键不可变太严格。要求密钥的标识不改变就足够了。不管怎么说,答案很好。如果钥匙的标识很重要的话,IdentityHashMap
将是一个不错的选择。然后你可以自由地改变你的键。@Federicoperaltachaffner据我所知,参考值是一个对象的标识。将同一性视为参考值的同义词,那么这个名称就完全有意义了。@Durandal好的,我理解你的意思。我的意思是关于equals()
合同的身份,即,如果您有一个个人
对象,该对象具有社会安全号码
、姓名
和姓氏
字段,那么关于equals()
的身份将仅由社会安全号码
字段定义,因为它在所有人中都是独一无二的。但实际上,这是平等而不是身份。我的错。@Luongbalin一个bucket更像是一个成对的链表:[(键1,值1),(键2,值2),…],而不是[(hashCode(键1,值1),(hashCode(键2,值2),…]
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
}
}
}