Skip to content

Instantly share code, notes, and snippets.

@squarepegsys
Created December 1, 2011 01:25
Show Gist options
  • Save squarepegsys/1412556 to your computer and use it in GitHub Desktop.
Save squarepegsys/1412556 to your computer and use it in GitHub Desktop.
Some thoughts on .hashCode and .equals in Java

Thoughts about .equals and .hashCode

Here is a little context: we were tracking down a memory leak in our application and saw this big HashMap in the dump file. The HashMap was from ehcache. The problem was that the objects that were used as the key did not implement .hashCode. Oops. We used Eclipse's generated .equals and .hashCode to get us by and that got us through the heat of the moment.

So, today, a couple of developers were on a PMD/FindBugs hunt and, when I got home from work, I had an email from one of them. Seems that there was a debate on if using the generated hashCode and equals was "good enough" or if something else should be done. They asked me to weigh in on the matter. So here I am -- spouting off something that may or may not be a good idea.

I think that .equals and .hashCode should be generated with care. If you hit the IDE's "generate hashCode and equals" button, you should figure out what properties in that object make it unique. Maybe something like "name" should be involved. To me, certainly something like "id" should not be (who cares if it comes from the database?). But it depends on what your use case are.

And they are related -- the objects that makes sense to decide equality should also be included in generating a hashCode. So much so that if

 x.equals(y)==true 

then

 x.hashCode()==y.hashCode()

See an interesting discussion on StackOverflow about this. See if you agree.

So if they are truly related to each other in such a strong way, they should be implemented identically -- in accordance to the DRY Principal.

Therefore, this is how I propose the Most Correct way to implement .hashCode and .equals:

  1. Implement .hashCode as tight and as correct as possible.
  2. .equals simply becomes : return this.hashCode()==that.hashCode()

That way, the relationship between .hashCode and .equals will always exist. Ff you add properties that effects equality, then you simply have to change the .hashCode method -- the .equals will use that in it's decision.

@mkolakow
Copy link

mkolakow commented Dec 1, 2011

On the other hand -- You've got me thinking. If there is even any remote possibility that two different objects could have the same hashcode, then this is simply not worth the risk. Essentially you are opening the door to an extremely nasty and hard to track down bug. Sure, unlikely to happen, but if it did, then you are potentially very screwed.

The Guava implementation is simply as follows:

for (Object element : a)
    result = 31 * result + (element == null ? 0 : element.hashCode());

Also - for what it's worth, see this discussion on StackOverflow

http://stackoverflow.com/questions/4360035/why-hashcode-can-return-the-same-value-for-different-objects-in-java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment