在这段代码中
object Program1 extends App {
val set = scala.collection.mutable.Set( "Abc", "def")
set += "ghi"
}
因为set在这种情况下是可变的,这意味着它会将元素添加到自身,并且不会创建新的集合,但是当我尝试显示集合的hashCode()
时,这样:
object Program1 extends App {
val set = scala.collection.mutable.Set( "Abc", "def")
println(set.hashCode)
set += "ghi"
println(set.hashCode)
}
我希望println()
语句将输出相同的哈希码,但它打印的不同,因为set对象没有更改,我们只是附加到现有的set然后为什么hashcode会有所不同。
答案 0 :(得分:3)
如果你在scala中查看hashCode
可变HashSet
的实现,你会发现它散列了所有内部元素。在散列时,我的scala版本会在MurmurHash3.unorderedHash(...)
调用时结束。其他人可能会有所不同。
如果你问为什么?我想这是因为Set("Abc", "def") != Set("Abc", "def", "ghi")
并且还与不可变HashSet
实现一致。这很有道理,我不知道为什么你会这样做。
更新
回答作者评论的其他解释
hashCode
是关于平等的,而不是关于同一个对象。规则是如果两个对象相等,那么它们应该返回相同的hashCode
。如果他们不是 - 他们最好返回不同(我说更好,因为它仍然可能通过碰撞返回相同)。这适用于所有对象。
考虑以下代码:
import scala.collection.mutable.Set
val s1 = Set(1)
val superSet = Set(s1)
println(superSet.contains(s1)) // prints true
println(superSet.contains(Set(1)) // still prints true
请注意,即使s1
和Set(1)
是内存中的两个不同对象,两者都会打印为true。这是因为他们的equals
和hashCode
返回相同的
现在这个实现存在一个小问题:
import scala.collection.mutable.Set
val superMap = scala.collection.mutable.Map.empty[Set[String], Boolean]
superMap += (set -> true)
println(superMap.contains(set)) // prints true
set += "ghi"
println(superMap.contains(set)) // prints false
println(superMap.contains(Set("Abc", "def"))) // still prints false
第二个println
打印false
。这是因为Map
无法再找到密钥,因为密钥已更改其hashCode
,但Map
仍会记住旧密钥。第三个println
仍未通过检查,因为即使hashCode
和Map
中的包含Set("Abc", "def").hashCode
相同,这些集合也会在之后无法进行等式检查。
这是一个众所周知的问题,没有好的解决方案,所以建议永远不要使用可变对象作为HashMap
的键。一般情况下,您不应将可变对象用于hashCode
- 检查然后equality
- 应用检查的任何结构。同样适用于HashSet
答案 1 :(得分:2)
此功能反映了所有hashCode()
和equals()
实施建议的内容:if a1.equals(a2)
然后a1.hashCode() == a2.hashCode()
。请查看此处的帖子以获取更多信息https://stackoverflow.com/a/256447/1154145