JavaAntiPatterns

Collection of bad coding practices

‘equals()’ is overridden while ‘hashCode()’ is not

with 5 comments

If you override equals() in your class, always provide a custom implementation of hashCode() that returns the same hash code value for two or more equal objects:

a.equals(b) → a.hashCode() == b.hashCode()

This is, in fact, a general contract defined by Java API Specification. Violation of this rule (which is likely the case if equals() method is overridden while hashCode() is inherited from Object) may cause numerous bugs and unexpected behaviours.

Note that the reverse rule: two or more unequal objects must have different hash codes, or

!a.equals(b) → a.hashCode() != b.hashCode()

though not required, is also highly recommended to be maintained wherever possible (except for the cases when a number of class instances is known to be greater than Integer.MAX_VALUE). Disregard of this rule (hash collisions) may reduce performance of HashMaps and Hashtables.

Example:

class Person {
    ...
    public boolean equals(Object o) {
        return (o instanceof Person) &&
               this.getName().equals(((Person)o).getName());
    }

    public int hashCode() {
       return this.getName().hashCode();
    }
}
Advertisements

Written by Alex

November 22, 2007 at 8:37 am

Posted in Objects

Tagged with , ,

5 Responses

Subscribe to comments with RSS.

  1. […] ‘equals()’ is overriden while ‘hashCode()’ is not […]

  2. I read your blog for a long time and should tell that your posts are always valuable to readers.

    How to Get Six Pack Fast

    April 15, 2009 at 3:17 pm

  3. Equal objects should have equal hashCodes. However, the following equation that you wrote is wrong:
    (a.hashCode() == b.hashCode()) == (a.equals(b))

    It should be:
    (a.equals(b)) -> (a.hashCode() == b.hashCode())

    Where ‘->’ is the logical “if/then”.
    If a equals b, then their hashCodes should be equal. However, having equal hashCodes does *not* imply equal objects.

    Two objects with equal hashcodes are not necessarily equal objects.

    A hashcode is an int.

    But, for example, a java.lang.Long object has a hashcode. Since there are more Long values than there are int values, multiple Long values must have the same hashcode. This is an example of the Pigeonhole Principle: http://en.wikipedia.org/wiki/Pigeonhole_principle

    Each pigeonhole here is a single ‘int’ value that could be returned from a hashCode method.

    So, two (or more) unequal values will often have the same hashCode.

    Monica

    October 14, 2009 at 2:13 pm

  4. Monica,

    Yes, in theory, you are right. It’s, of course, impossible to hold this rule (different objects -> different hashcodes and vice versa) if a number of instances is greater than Integer.MAX_VALUE.

    However, in all other cases I would still consider violation of this as an extremely bad practice which may lead to numerous problems with (e.g.) Java Collections. For instance, the simplest valid hashcode() implementation would return a static value (say, 0). It’s absolutely valid, but performance of HashMaps would be horrible. So, it’s obviously an antipattern.

    I think that the problem mentioned by you should be included into the article, or maybe, the article should be divided to two different antipatterns.

    Thanks!

    Alex

    October 14, 2009 at 4:13 pm

  5. Updated.

    Alex

    October 14, 2009 at 6:17 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: