2016-09-29 4 views
1

スカラのケースクラスのhashCodeは、そのフィールドによってのみ決定されていたという印象を受けました。その結果、hashCodeをキャッシュすることは、不変のケースクラスに対して安全であると考えました。私は間違っているようキャッシュされたhashCodeを持つスカラケースクラス

は思え:

case class Foo(s: String) { 
    override val hashCode: Int = super.hashCode() 
} 

val f1 = Foo("foo") 
val f2 = Foo("foo") 

println(f1.hashCode == f2.hashCode) // FALSE 

誰もが、ここにしてください何が起こっているのかを説明してもらえますか?

補遺 - ただ、比較のために:ケースクラスのインスタンスの

case class Bar(s: String) 

val b1 = Bar("bar") 
val b2 = Bar("bar") 

println(b1.hashCode == b2.hashCode) // TRUE 

答えて

6
この値のわからない

、しかし、あなたはScalaRuntime._hashCodeの実装インライン化することができます

case class Foo(s: String) { 
    override val hashCode: Int = scala.util.hashing.MurmurHash3.productHash(this) 
} 
+0

はい、これは良い解決策です:パブリックAPIに基づいた実装でオーバーライドされていない場合と同じ動作(フィールドのみに基づいたハッシュ)、まだメモされている - ありがとう! – netzwerg

0

toStringはないhashCode

+0

「hashCode」がオーバーライドされていない場合があります。私の補遺を参照してください。 – netzwerg

1

あなたが何を意味するかわからない「キャッシュされたhasCode」によって、そのフィールドのみに依存するが、。 .. から構築されたカスタムソリューションでhashCodeをオーバーライドしたので、falseが得られます。このオーバーライドを削除すると、期待値が得られます。

+0

不変のケースクラスのhashCodeをメモしたいと思いました。しかし、私は 'super.hashCode()'の代わりに 'def def hashCode():Int = ScalaRunTime._hashCode(this)'を使っていたはずです!これは公開APIではありません...ありがとう! – netzwerg

1

Rumokuの答え@は本当にここで何が起こっているかでやっています。 case class Fooを宣言すると、case class Foo extends AnyRef with Product with Serializablescalac-Xprint:typerオプションを参照)にコンパイルされます。さらに、hashCodeの実装も次のように生成されます:override def hashCode: Int = scala.runtime.ScalaRunTime._hashCode(this)。ただし、hashCodeをオーバーライドすると、この実装は生成されません。キーはProductでもSerializableでもhashCodeを実装していないので、super.hashCodeを呼び出したときに取り上げる実装は、AnyRef/Any/Objectのデフォルトの実装です。

関連する問題