I'm having some trouble writing a hashCode()
method for a class I created. This class is meant to be used inside a TreeSet, and as such, it implements Comparable. The class has the following variables:
public class Node implements Comparable<Node> {
Matrix matrix;
int[] coordinates= new int[2];
Node father;
int depth;
int cost;
Here's the implementation of the compareTo()
method. I want the TreeSet
to organize these Node structures by their cost, therefore, compareTo()
returns the result of a simple subtraction.
public int compareTo(Node nodeToCompare) {
return this.cost - nodeToCompare.cost;
}
I also implemented an equals()
method.
public boolean equals(Object objectToCompare) {
if(objectToCompare== this) {return true;}
if(objectToCompare== null || objectToCompare.getClass()!= this.getClass()) {return false;}
Node objectNode= (Node) objectToCompare;
return this.father.equals(objectNode.father) &&
this.depth== objectNode.depth &&
this.cost== objectNode.cost &&
this.matrix.equals(objectNode.matrix) &&
Arrays.equals(this.coordinates, objectNode.coordinates);
}
Having said all of that, I have a few questions:
- Since I implemented a new
equals()
method, should I implement a newhashCode()
method? - How can I go about implementing a new hashCode
method()
with those variables? (Note that the variable matrix of the type Matrix has ahashCode()
method implemented)
That's all!
Your
compareTo
method is not consistent with yourequals
method: yourcompareTo
method says that two instances are equivalent if they have the samecost
— such that aTreeSet
can only ever contain at most one instance with a givencost
— but yourequals
method says that they're only equivalent if they have the samecost
and are the same in various other ways.So, assuming that your
equals
method is correct:compareTo
method to be consistent with it.hashCode
method that is consistent with it. I recommend using the same sort of logic as is used byjava.util.List.hashCode()
, which is a straightforward and effective way to assemble the hash-codes of component objects in a specific order; basically you would write something like:If your collection is small you can return constant from hashCode method. It use for quick finding. hashCodes is like the boxes, which keep elements. Rules are:
Then you return constant, you obey these 2 rules, but it can significantly decrease perfomance on not small lists (because JVM will look for in all elements, and not in elements in the same box only). But return constant is the bad approach.
PS: Sorry for my writing. English is not my native language.
PPS: usualy you have to implement hashCode method in the same way as equals (use same elements)
The contract for the hashCode method states that if two objects are equal, then calling hashCode() should give you the same integer result. The opposite does not have to be true, i.e. if two hashCodes are the same the objects don't have to equal each other.
Looking at your equals method (which needs variable translation btw), you can add the hashCodes of all the internal member variables that need to be equals for your equals method to give true. e.g.
The above assumes that matrix and father are never nulls, you need to make sure that you check for nulls if that's not the case.
If you feel more adventurous you can multiply a few of the above with a prime to ensure you don't get hashCode collisions for different data (this will help improve performance if you are using your class in hashTables and hashMaps). If you need to cater for nulls, the above method can be written a bit better like this:
Intellij IDEA can do this as a ' right-click' feature. Just seeing it done correctly will teach you alot.
And you should override both in any case.