[英]List.Contains returns false, even though it seems it should return true
[英]Scala List.contains(x) return false, but exists(_.== x) returns true
我在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源代碼,但我認為包含將基本上作為第二個存在的調用實現。
你沒有覆蓋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
方法不會被contains
調用,因為您沒有覆蓋Any
上的默認實現。 這樣做的線索是編譯器不會抱怨缺少override
修飾符。
正確的方法簽名將是
override def equals(other: Any): Boolean
當你調用List(state).exists( _.equals (state.clone)
,它解析為你的實現,因為編譯器知道參數的類型是State
。因此它選擇了專用於方法的重載變量。那種類型。
contains
的簽名始終采用Any
類型的參數,無論List
的類型參數如何,因此方法調用將解析為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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.