0

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"){}
zero323
  • 322,348
  • 103
  • 959
  • 935
Robert
  • 3
  • 3

1 Answers1

2

I think you need to override hashcode too. See the answer here:

Why do I need to override the equals and hashCode methods in Java?

Community
  • 1
  • 1
Chrs
  • 862
  • 6
  • 10
  • Yes, that seems to have been it. I change the object 'key', which changed its hashcode of the object. Although the object was still found in the keySet, it could no longer found in the bucket which was determined by its previous hashcode. I set my method hashCode to ID.hashCode, so that it now returns the hashcode of my unique identification string. Thank you so much! – Robert Jan 24 '17 at 15:57