Contains()在List和TreeSet上的行为不同

Rya*_*rio 1 scala treeset

我遇到了一个奇怪的情况,其中contains()函数似乎在Scala中的List和TreeSet之间有所不同,我不知道为什么或如何解决它.

DataStructure为了简洁而创建了一个类.它包含两个元素:坐标对(i, j)Int.(它比这更复杂,但是在这个MWE中,这就是它的样子)它有一个自定义的比较器,它将被排序Int,并且我已经被覆盖hashCode,equals因此包含相同坐标对的两个元素(i, j)被视为相等而不管这个Int.

当我将一个实例DataStructure放入a List和a时TreeSet,程序找到完全匹配没有问题.然而,检查具有相同的坐标对的,但不同的新元素时Int,在List.contains返回trueTreeSet.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
  }    
}
Run Code Online (Sandbox Code Playgroud)

司机程序

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)
}
Run Code Online (Sandbox Code Playgroud)

输出:

list contains exact match: true
list contains match on first element: true
TreeSet contains exact match: true
TreeSet contains match on first element: false
Run Code Online (Sandbox Code Playgroud)

Joe*_*oel 7

几乎可以肯定的List.contains是检查equals每个元素以找到匹配,而TreeSet.contains在树上行走并使用compare查找匹配.

你的问题是你compare的不一致equals.我不知道你为什么这样做,但不要:

https://www.scala-lang.org/api/current/scala/math/Ordered.html

"重要的是,Ordered [A]实例的equals方法与compare方法一致."