関数がScalaのListとTreeSetの間で動作が異なるように見える奇妙なケースに遭遇しましたが、それを解決する理由や方法がわかりません。ListsとTreeSetで異なる動作をする
簡潔にするため、DataStructure
というクラスを作成しました。これには、座標ペア(i, j)
とInt
という2つの要素が含まれています。 (これよりも複雑ですが、このMWEではこれが見えます)Int
でソートされるカスタムコンパレータがあり、hashCode
とequals
をオーバーライドして、同じ座標ペア(i, j)
を含む2つの要素が処理されますInt
にかかわらず等しいとします。私は両方のList
とTreeSet
へDataStructure
のインスタンスを入れると
は、プログラムが完全一致を見つける問題はありません。ただし、同じ座標ペアであるが、Int
が異なる新しい要素を確認する場合、List.contains
はtrue
を返し、TreeSet.contains
はfalse
を返します。なぜこれが起こり、どのように解決できますか?
これは最低限の作業例に減少私のコードです:
クラスDataStructure
package foo
class DataStructure(e1: (Int, Int), e2: Int) extends Ordered[DataStructure] {
val coord: (Int, Int) = e1
val cost: Int = e2
override def equals(that: Any): Boolean = {
that match {
case that: DataStructure => if (that.coord.hashCode() == this.coord.hashCode()) true else false
case _ => false
}}
override def hashCode(): Int = this.coord.hashCode()
def compare(that: DataStructure) = {
if (this.cost == that.cost)
0
else if (this.cost > that.cost)
-1 //reverse ordering
else
1
}
}
ドライバプログラム
package runtime
import foo.DataStructure
import scala.collection.mutable.TreeSet
object Main extends App {
val ts = TreeSet[DataStructure]()
val a = new DataStructure((2,2), 2)
val b = new DataStructure((2,3), 1)
ts.add(a)
ts.add(b)
val list = List(a, b)
val listRes = list.contains(a) // true
val listRes2 = list.contains(new DataStructure((2,2), 0)) // true
val tsRes = ts.contains(a) // true
val tsRes2 = ts.contains(new DataStructure((2,2), 0)) // FALSE!
println("list contains exact match: " + listRes)
println("list contains match on first element: " + listRes2)
println("TreeSet contains exact match: " + tsRes)
println("TreeSet contains match on first element: " + tsRes2)
}
出力:
list contains exact match: true
list contains match on first element: true
TreeSet contains exact match: true
TreeSet contains match on first element: false
あなたはすでに答えを持っていますが、異なるオブジェクトに等しいハッシュコードを持つことができるので、hashcodeをequalsとして使用することは悪い考えです。 – puhlen