0

When I was trying to get an error from a hashmap with one record I kept getting null. Finally i tested it in the following way:

Iterator<Position> it = pieces.keySet().iterator();
    while (it.hasNext()){
        System.out.println("object from key >> " + pieces.get(it.next()));
    }
    Iterator<Piece> itt = pieces.values().iterator();
    while (itt.hasNext()){
        System.out.println("direct object >> " + itt.next().getPosition());
    }

The output I got was:

object from key >> null
direct object >> application.Position@37

The code I have shown was used as it is without anything else in between.

Regarding the position object, I had overridden the hashCode() function to return the hashCode based on the values of the Position class. So when the variables within the object are changed, the HashCode is changed. The above code works well before the position object's value is changed. But once I change the I am getting a null through the key.

Neville Nazerane
  • 6,622
  • 3
  • 46
  • 79
  • 2
    You absolutely cannot change any values over which the `hashCode` is calculated over once a key is in the `Map`. You **must** `remove` and re-`add` the key. – Boris the Spider Dec 03 '15 at 17:55
  • so you mean to say the HashMap object saves the hashCodes on insert and doesn't call the hashCode() function when i call the HashMap's get() function? – Neville Nazerane Dec 03 '15 at 17:57
  • How do you think a `HashMap` works? How does it achieve (amortised) `O(1)` performance? – Boris the Spider Dec 03 '15 at 17:57
  • well I don't know how a HashMap works. That's why i was asking. I din't know its order of performance either. So does it not call the hashCode() function each time the get() is called? – Neville Nazerane Dec 03 '15 at 18:01
  • 1
    Read [this](http://stackoverflow.com/a/32377512/2071828). It should answer all your questions. It is also helpful to start with [a tutorial](https://docs.oracle.com/javase/tutorial/collections/interfaces/map.html) rather than coming straight here. – Boris the Spider Dec 03 '15 at 18:08
  • What is the type of the keys? What is the type of `pieces`? You're talking about the `Position` object changing, but that appears to be an attribute of the value, not the key. Are the `Position` objects the keys in your map? As others have said, changing the hash code of your keys after they are put into a hash-based container will break that container. – David Conrad Dec 03 '15 at 18:16
  • yes, positions are the keys. i am using a map to find the pieces at the map. and thanks, i got what others were saying and will be using @BoristheSpider's idea of removing and readding – Neville Nazerane Dec 03 '15 at 23:30

1 Answers1

5

See the relevant documentation for Map:

Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.

A map data structure inspects your object at insertion time in order to determine where it should live (for a HashMap it inspects the hashCode() and puts it in a particular bucket, for TreeMap it compares it against other keys and puts it in a particular branch of the tree, etc.). Maps provide efficient lookup because they then only look where the object is expected to be, and don't search the other buckets / rest of the tree. If you mutate the object after storing it in the map in a way that affects where the map would store it, you break the assumptions the map is making. It will look in the expected bucket, not find it, and give up.

I go into some more detail about the assumptions HashMap makes and why in this related answer.

Community
  • 1
  • 1
dimo414
  • 47,227
  • 18
  • 148
  • 244