2015-12-18 17 views
0

在這一段代碼的HashCode在階可變集合

object Program1 extends App { 

    val set = scala.collection.mutable.Set("Abc", "def") 
    set += "ghi" 

} 

自組是可變的在此情況下,意味着它將元素添加到本身和沒有新的一組將被創建,但是當我試圖顯示hashCode()設定這樣的:

object Program1 extends App { 

val set = scala.collection.mutable.Set("Abc", "def") 
println(set.hashCode) 
set += "ghi" 
println(set.hashCode) 

} 

我預計println()語句將輸出相同的哈希碼,但它印不同,如設置對象沒有改變,我們只是附加到現有的設置,那麼爲什麼哈希碼是不同的正在添加。

回答

3

如果你看看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,即使s1Set(1)是內存中的兩個不同的對象。這是因爲他們的equalshashCode返回相同

現在有一個小問題,這種實現:

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仍然無法通過檢查,因爲即使MapSet("Abc", "def").hashCode中的hashCode包含hashCode相同,這些集合之後也不會通過相等性檢查。

這是一個衆所周知的問題,沒有很好的解決方案,所以建議不要使用可變對象作爲HashMap的鍵。一般而言,不應將可變對象用於任何應用hashCode -check和equality -check的結構。同樣的事情適用於HashSet

+0

但是即使向其添加新元素後,設置對象也是相同的 – Aamir

+0

即使在向其添加新元素之後,set仍然指向相同的內存位置。 – Aamir

+0

@Aamir請參閱更新 – Archeg