簡體   English   中英

Scala可變集合中的HashCode

[英]HashCode in scala mutable collection

在這段代碼中

object Program1 extends App {

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

}

因為在這種情況下set是可變的,這意味着它將向其自身添加元素,並且不會創建新的set,但是當我嘗試顯示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會有所不同。

如果在scala中查看可變HashSet hashCode實現,您會發現它哈希了其所有內部元素。 散列時,我的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

請注意,即使s1Set(1)是內存中的兩個不同對象,它們都顯示為true。 這是因為它們的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仍然未通過檢查,因為即使包含hashCodeMapSet("Abc", "def").hashCode相同,套之后失敗的平等檢查。

這是一個眾所周知的問題,沒有好的解決方案,因此建議不要使用可變對象作為HashMap的鍵。 通常,對於任何應用了hashCode -check然后equality -check的結構,都不應使用可變對象。 HashSet同樣適用

此功能反映了所有hashCode()equals()實現所推薦的功能:如果a1.equals(a2)a1.hashCode() == a2.hashCode() 在這里查看帖子以了解更多信息https://stackoverflow.com/a/256447/1154145

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM