Search code examples
javaequalshashcode

Is checking hashCode() equality a valid approach to implement equals(Object obj)?


My hashCode method ensures that equal objects have equal hash codes. My implementation also guarantees that the contrapositive is true, in that equal hash codes imply object equality. Doing something like:

   @Override
    public boolean equals(Object obj) {
        if (this == obj) {return true;}
        if (obj == null) {return false;}
        if (getClass() != obj.getClass()) {return false;}
        return (obj.hashCode() == this.hashCode());
    }

seems an obvious choice, but I don't see this often. Is this is a good idea in my case, or am I missing something?

Also, I'm not sure if this is relevant, but the hashCode and equals methods are in generated classes (and obviously are themselves generated). The reason I mention this is to highlight the fact that these methods will not be maintained manually per say. They are in classes that are created at compile time and are not intended to be changed unless the schema they are based on changes.


Solution

  • If, as the question says, your hashCode implementation really does guarantee that unequal objects have unequal hash codes, then in principle there is nothing wrong with what you are doing. Your equals method is checking a property that is equivalent to equality, so the behavior is as intended. You should re-check that guarantee, though; remember that no matter how clever you are, you can only store 32 bits of information in an int, which means that most non-trivial objects will necessarily have hash colisions.

    However, there are a few caveats. First is clarity: if you implement equals this way, anyone using your code has to look at your hashCode implementation to find out what properties determine equality. Second is speed: if your hash code implementation is significantly slower than simply checking equality of the relevant properties (including boolean shortcutting in that calculation), then it may be worth re-implementing the logic in the equals function to avoid the speed penalty. Third is coupling: implementing equals in this manner means that it depends on that property of hashCode, and any future change to hashCode has to either preserve that property or move the logic into equals.