Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java HashMap containsKey always false

I have the funny situation, that I store a Coordinate into a HashMap<Coordinate, GUIGameField>.

Now, the strange thing about it is, that I have a fragment of code, which should guard, that no coordinate should be used twice. But if I debug this code:

if (mapForLevel.containsKey(coord)) {
    throw new IllegalStateException("This coordinate is already used!");
} else {
    ...do stuff...
}

... the containsKey always returns false, although I stored a coordinate with a hashcode of 9731 into the map and the current coord also has the hashcode 9731.

After that, the mapForLevel.entrySet() looks like:

(java.util.HashMap$EntrySet) [(270,90)=gui.GUIGameField@29e357, (270,90)=gui.GUIGameField@ca470]

What could I have possibly done wrong? I ran out of ideas. Thanks for any help!

public class Coordinate {
    int xCoord;
    int yCoord;

    public Coordinate(int x, int y) {
        ...store params in attributes...
    }

    ...getters & setters...

    @Override
    public int hashCode() {
        int hash = 1;
        hash = hash * 41 + this.xCoord;
        hash = hash * 31 + this.yCoord;
        return hash;
    }
}
like image 802
Dennis Avatar asked Jun 15 '26 05:06

Dennis


2 Answers

You should override equals in addition to hashCode for it to work correctly.

EDIT : I have wrongly stated that you should use hashCode in your equals - this was not correct. While hashCode must return the same result for two equal objects, it still may return the same result for different objects.

like image 178
kostja Avatar answered Jun 16 '26 18:06

kostja


It seems that you forgot to implement equals() method for your coordinate class. This is required by contract. Hah compares 2 entries with the same hash code using equals. In your case the Object.equals() is called that is always different for 2 different object because is based on reference to the object in memory.

like image 36
AlexR Avatar answered Jun 16 '26 18:06

AlexR