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

use*_*292 4 collections scala contains list 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 equals (other: State) : Boolean = {
    //println("Comparing " + trackmap + " to " + other.trackmap)
    trackmap == other.trackmap  

  }

  def == (other: State) : Boolean = {
    this equals other
  }
}
Run Code Online (Sandbox Code Playgroud)

我的相关测试:

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

所有这些都通过了,除了最后一个,我期望它应该通过.我没有看过Scala源代码,但我认为包含将基本上作为第二个存在的调用实现.

Ama*_*any 12

你没有覆盖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
    }
}
Run Code Online (Sandbox Code Playgroud)

请参阅,Scala中的equals方法采用Any not State类型的参数,您需要为其添加override关键字.

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

  • 请注意,这也可以通过以下事实证明:"List(state).exists(_ == state.clone)"返回`true`,`List(state).exists(_ ==(state.clone:Any) ))`返回`false`. (4认同)
  • 在`equals`实现中使用模式匹配比`isInstanceOf` /`asInstanceOf`组合更加惯用. (2认同)