Contains() 对 List 和 TreeSet 的作用不同
Contains() acting different on List and TreeSet
我 运行 遇到了一个奇怪的情况,其中 contains()
函数在 Scala 中的 List 和 TreeSet 之间的工作方式似乎不同,我不确定为什么或如何解决它。
为了简洁起见,我创建了一个名为 DataStructure
的 class。它包含两个元素:一个坐标对 (i, j)
和一个 Int
。 (它比那更复杂,但在这个 MWE 中,它看起来像这样)它有一个自定义比较器,将按 Int
排序,我已经覆盖了 hashCode
和 equals
因此无论 Int
.
包含相同坐标对 (i, j)
的两个元素都被视为相等
当我将 DataStructure
的实例同时放入 List
和 TreeSet
时,程序可以毫无问题地找到完全匹配项。但是,当检查具有相同坐标对但不同 Int
的新元素时,List.contains
returns true
而 TreeSet.contains
returns false
。为什么会发生这种情况,我该如何解决?
这是我的代码简化为最小工作示例:
Class 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
几乎可以肯定 List.contains
正在检查每个元素的 equals
以找到匹配项,而 TreeSet.contains
正在遍历树并使用 compare
来找到匹配项。
你的问题是你的compare
和你的equals
不一致。我不知道你为什么要那样做,但不要:
https://www.scala-lang.org/api/current/scala/math/Ordered.html
"It is important that the equals method for an instance of Ordered[A] be consistent with the compare method."
我 运行 遇到了一个奇怪的情况,其中 contains()
函数在 Scala 中的 List 和 TreeSet 之间的工作方式似乎不同,我不确定为什么或如何解决它。
为了简洁起见,我创建了一个名为 DataStructure
的 class。它包含两个元素:一个坐标对 (i, j)
和一个 Int
。 (它比那更复杂,但在这个 MWE 中,它看起来像这样)它有一个自定义比较器,将按 Int
排序,我已经覆盖了 hashCode
和 equals
因此无论 Int
.
(i, j)
的两个元素都被视为相等
当我将 DataStructure
的实例同时放入 List
和 TreeSet
时,程序可以毫无问题地找到完全匹配项。但是,当检查具有相同坐标对但不同 Int
的新元素时,List.contains
returns true
而 TreeSet.contains
returns false
。为什么会发生这种情况,我该如何解决?
这是我的代码简化为最小工作示例:
Class 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
几乎可以肯定 List.contains
正在检查每个元素的 equals
以找到匹配项,而 TreeSet.contains
正在遍历树并使用 compare
来找到匹配项。
你的问题是你的compare
和你的equals
不一致。我不知道你为什么要那样做,但不要:
https://www.scala-lang.org/api/current/scala/math/Ordered.html
"It is important that the equals method for an instance of Ordered[A] be consistent with the compare method."