如果你看看hashCode
在scala中實現一個可變的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
注意兩個打印true,即使s1
和Set(1)
是內存中的兩個不同的對象。這是因爲他們的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
仍然無法通過檢查,因爲即使Map
和Set("Abc", "def").hashCode
中的hashCode
包含hashCode
相同,這些集合之後也不會通過相等性檢查。
這是一個衆所周知的問題,沒有很好的解決方案,所以建議不要使用可變對象作爲HashMap
的鍵。一般而言,不應將可變對象用於任何應用hashCode
-check和equality
-check的結構。同樣的事情適用於HashSet
但是即使向其添加新元素後,設置對象也是相同的 – Aamir
即使在向其添加新元素之後,set仍然指向相同的內存位置。 – Aamir
@Aamir請參閱更新 – Archeg