Reputation: 5755
I am trying to check for and remove elements, using a HashMap in Java. Its keys are a type I created called ClusterKey, and its values are a type I created called ClusterValue.
Here is the code that is causing issues:
ClusterKey ck = new ClusterKey(Long.parseLong(split[0].split("=")[1]),
Integer.parseInt(split[1].split("ey")[1]));
if (arg == 0) keys.put(ck, new ClusterValue(index, false));
if (arg == 1) {
if (keys.containsKey(ck)) {
index = keys.get(ck).messageNo;
keys.remove(ck);
}
keys.put(ck, new ClusterValue(index, true));
}
The problem is that even when the ClusterKey is the same as an existing ClusterKey, containsKey() and remove() do not seem to recognize it as equal. I have implemented equals() in class ClusterKey to override Java's equals() method, as follows:
class ClusterKey {
long firstKey;
int secondKey;
public ClusterKey(long firstKey, int secondKey) {
this.firstKey = firstKey;
this.secondKey = secondKey;
} public boolean equals(Object otherKey) {
return this.firstKey == ((ClusterKey) otherKey).firstKey && this.secondKey == ((ClusterKey) otherKey).secondKey;
}
}
So, I'm quite confused. Thanks so much for your help.
Regards, Rebecca
UPDATE: Thank you for your advice and feedback on my code. I was able to solve the problem by adding hashCode() to ClusterKey, as follows:
} public boolean equals(Object otherKey) {
return this.firstKey == ((ClusterKey) otherKey).firstKey && this.secondKey == ((ClusterKey) otherKey).secondKey;
} public int hashCode() {
return (int) firstKey + secondKey;
}
Upvotes: 2
Views: 2063
Reputation: 51711
For any Hash enabled data structure (like HashMap
, HashSet
) to work correctly its elements must override hashCode()
in addition to the equals()
method. The reason being that the hash code is used to identify the bucket in which to put the element (during insertion) or search in (using equals()
during a lookup).
If you do not override hashCode()
, the default implementation from Object#hashCode()
is used which would return different values even for the objects that you consider equivalent (the equals()
method returns true for).
This is why your
hashMap.containsKey(ClusterKey key)
calls are failing in spite of the key already being present. Since, the hash codes don't match the HashMap
never looks for the key in the right bucket. Hence, your equals()
never gets called here.
Upvotes: 3
Reputation: 178263
You will need to implement hashCode()
, not just equals
, for your ClusterKey
to work well as a key in a HashMap
.
Specifically, quoting from the linked Javadocs:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
Upvotes: 3