Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala List.contains(x)返回false,但exists(==x)返回true_List_Scala_Collections_Contains_Exists - Fatal编程技术网

Scala List.contains(x)返回false,但exists(==x)返回true

Scala List.contains(x)返回false,但exists(==x)返回true,list,scala,collections,contains,exists,List,Scala,Collections,Contains,Exists,我正在Scala中处理一些简单的数据结构和集合,我注意到了我认为奇怪的行为。这是目标: class State (protected val trackmap: Map[Int, List[String]]) { override def clone : State = { new State(Map() ++ trackmap) } override def toString = { "State: " + trackmap.toString } def equa

我正在Scala中处理一些简单的数据结构和集合,我注意到了我认为奇怪的行为。这是目标:

class State (protected val trackmap: Map[Int, List[String]]) {

  override def clone : State = {
    new State(Map() ++ trackmap)
  }

  override def toString = { "State: " + trackmap.toString }

  def equals (other: State) : Boolean = {
    //println("Comparing " + trackmap + " to " + other.trackmap)
    trackmap == other.trackmap  

  }

  def == (other: State) : Boolean = {
    this equals other
  }
}
以及我的相关测试:

  test("state equality") {
    val state = new State( Map(1 -> List("engine"), 2 -> List("a"), 3 -> List("b")) )

    expect(true) { state equals state.clone }
    expect(true) { state == state.clone }
    expect(false) { state == new State(Map(1 -> List("a"))) }
    expect(false) { state equals new State(Map(1 -> List("a"))) }

    expect(true) { List(state).exists( _.equals (state.clone) )}
    expect(true) { List(state).exists( _.== (state.clone) )}
    expect(true) { List(state).contains( state.clone )}
  }

他们都通过了,除了最后一个,我想应该通过。我没有查看Scala源代码,但我假设contains基本上会作为第二个exists调用来实现。

您的
equals
方法没有被
contains
调用,因为您没有覆盖
Any
上的默认实现。这方面的线索是,编译器不会抱怨缺少
重写
修饰符

正确的方法签名是

override def equals(other: Any): Boolean
当您调用
List(state).exists(u.equals(state.clone)
)时,它解析为您的实现,因为编译器知道参数的类型是
state
。因此它选择了专用于该类型的方法的重载变量


contains
的签名始终采用类型为
Any
的参数,而不管
列表的类型参数是什么,因此方法调用将解析为
equals

的默认实现,因为您没有覆盖Scala的实际equals方法,这就是它行为异常的原因。 重新编写equals方法,如下所示:

override def equals (other: Any) : Boolean = {
    other match{
      case that: State =>
        //println("Comparing " + trackmap + " to " + other.trackmap)
        trackmap == that.trackmap
      case _ => false
    }
}
请参阅,Scala中的equals方法接受类型为Any not State的参数,您需要为其添加
override
关键字


顺便说一句,您甚至不需要==方法,因为Scala会自动将其重新映射为equals方法!

您对
equals和
=
的实现不是它应该的样子。因此Scala有
case

你的班级会是这样的

case class State(protected val trackmap: Map[Int, List[String]]) {

  override def clone: State = {
    new State(Map() ++ trackmap)
  }

  override def toString = { "State: " + trackmap.toString }
}
如果您想手动实现它们,则需要实现
Equals
特性,并覆盖以下方法:

override def canEqual(other: Any) = 
  other.isInstanceOf[State]

override def equals(other: Any) = {
  other match {
    case that: State => (that canEqual this) && trackmap == that.trackmap
    case _ => false
  }
}

override def hashCode() = {
  val prime = 41
  prime + trackmap.hashCode
}

请注意,这也可以通过以下事实来证明:
List(state).exists(==state.clone)
返回
true
List(state).exists(==state.clone:Any))
返回
false
。在
equals
实现中使用模式匹配将比
isInstanceOf
/
asInstanceOf
组合更加惯用。是的,我现在就解决它。谢谢你的建议(我对Scala还是有点Javaish)