Answered! I have tried to boil down the problem to the following code and output. Short explanation: if the key cannot be found in hashMap we print out the different notions of equality: ==, equals, eq and finally the hashCode and a repitition of hashMap.contains(key). It is a single-threaded application!
val hashMap : collection.immutable.HashMap[State,State] = transition
val key : State = currentState
if (! hashMap.contains(key))
hashMap.keySet.map { entry : State =>
if (entry.ID == key.ID) {
println("================================")
println("entry.ID is " + entry.ID)
println("entry == key is " + (entry == key))
println("entry.equals(key) is " + entry.equals(key))
println("entry eq key is " + entry.eq(key))
println("entry.hashCode == key.hashCode is " + (entry.hashCode == key.hashCode))
println("hashMap.contains(key) is " + hashMap.contains(key))
System.exit(0)
}
}
else
println(s"""Key "${key.ID}" found""")
The code is executed repeatedly during program execution, producing the output:
Key "Start" found
Key "Start" found
Key "Start" found
================================
entry.ID is Start
entry == key is true
entry.equals(key) is true
entry eq key is true
entry.hashCode == key.hashCode is true
hashMap.contains(key) is false
I don't understand how this is possible. I can even show that hashMap.keySet contains elements which are not contained in hashMap, which I believe to be inconsistent. Note that 'key' is the instance of an object (not a class) extending ArrayBuffer, whose 'equals' function has been overridden to compare on the ID. However, from all I know, that should not matter as the equals function matters. Help would much be appreciated.
Edit: Definition of State and Start:
abstract class State(val ID:String) extends ArrayBuffer[Result] {
override def canEqual(that: Any): Boolean = that.isInstanceOf[State]
override def equals(that: Any): Boolean = that match {
case that:State => ID == that.ID
case _ => false
}
}
object START extends State("Start"){}