My co-worker was overriding the equals()
method. My response was, have you also overridden the hashCode()
method? His response was because we won't use hash map or hash set, it shouldn't really matter if we override hashCode()
. Is that correct?
6 Answers 6
Yes he is factually right - however, if you need to put your objects in a hash-based collection one day, you will have to add hashcodes everywhere, which can be annoying + on that day you might implement your hashcode incorrectly (i.e. not consistent with equals) because you miss some subtlety in the equals method...
Considering that most IDEs provide an auto equals/hashcode generation feature, I see little reason not to create both.
Another way to look at it is: when you override a method from a parent class, you should follow the contract defined by that parent class. In the case of Object, the javadoc of equals is pretty clear:
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
So unless you have a real design reason not to override hashcode, the default decision should be to follow the parent class contract and override neither or both.
-
2+1 But on the other hand, if
equals
is what the code depends on now, there's a very high chance ofhashCode
falling behind the changes toequals
, once again ending up inconsistent with it. The best compromise, to my eyes, would be a simplereturn 1;
---at least it's technically correct.Marko Topolnik– Marko Topolnik2013年02月08日 21:00:36 +00:00Commented Feb 8, 2013 at 21:00 -
7My issue with
return 1;
is that it seems likely to lead to silent, difficult-to-debug performance problems if you useHashSet
later. Instead, I'd implementhashCode()
asthrow new UnsupportedOperationException()
, which requires minimal effort, but makes it obvious when you come back and use aHashSet
later that you didn't bother implementinghashCode()
the first time.Louis Wasserman– Louis Wasserman2013年02月08日 21:19:47 +00:00Commented Feb 8, 2013 at 21:19 -
1@LouisWasserman Throwing an exception if you really don't want to implement hashcode is a very good idea indeed.assylias– assylias2013年02月08日 21:29:33 +00:00Commented Feb 8, 2013 at 21:29
-
Thank you very much everyone! assylias - what do you mean by "you will have to add hashcodes everywhere" in the first paragraph? Doesn't my co-worker just need to add the
hashCode()
method back to that one class which he overridesequals()
?user1739658– user17396582013年02月08日 23:19:38 +00:00Commented Feb 8, 2013 at 23:19 -
If only one class is involved then yes you only have one method to add - I thought he wanted to apply it to many classes.assylias– assylias2013年02月08日 23:58:30 +00:00Commented Feb 8, 2013 at 23:58
If you override equals()
, do override hashCode()
as well. Even if you don't use hashCode()
now, you or somebody else might use it.
For more on this topic, check the excellent SO answer
It's a code smell. Findbugs for example will warn you if you override either hashCode or equals without overriding the other. You should override both so that they are consistent with one another (that is, a.equals(b) => a.hashCode() == b.hashCode()).
A little effort now may save a lot of headaches later.
-
or.. having hashCode on a class not designed to be a key (being mutable for instance) can cause you a lot of more trouble later. Not having overridden hashCode will be caught immediately, having broken hashCode is much harder to trace.bestsss– bestsss2013年02月10日 14:23:48 +00:00Commented Feb 10, 2013 at 14:23
-
if it's not supposed to be a key in a hash structure you can throw an exception inside hashcode... there is precedent for that for example in Google protocol buffers when the protocol message contains a MessageSetsjr– sjr2013年02月11日 18:38:13 +00:00Commented Feb 11, 2013 at 18:38
-
While a good solution if has the potent to break existing code (overall no one expects
hashCode()
to throw an exception). I know code that uses hashCode to test for null (i.e. expecting NPE) [bogus getClass() would have been better] - so again it might be ok - but proposing it default is a bit risky.bestsss– bestsss2013年02月11日 20:12:14 +00:00Commented Feb 11, 2013 at 20:12
You must override hashCode in every class that overrides equals. Failure to do so will result in a violation of the general contract for Object.hashCode, which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.
Effective Java Item 9: Always override hashCode when you override equals.
If your class is a public class then you can not control how your classes will be used in future development. Without looking into source code (or through reflection) there is no way to know whether this class has overriden the hasCode method or not and the user will be surprised by the result if they use it in any hash based collections.
-
That's true! I think my co-worker probably didn't think about releasing his code for other people to use and that he is probably going to be the main person working on the framework.user1739658– user17396582013年02月08日 23:45:10 +00:00Commented Feb 8, 2013 at 23:45
Actually assume that you create two different objects without overriding equals and hashCode methods. And then if you call equals method java calls hashCode method implicitly then checks the equality of hashcodes.
Overriding hashCode method is enough for checking equality of two objects. And it will be useful for future. You can use this class on collections.
Otherwise if you implement just equal method, it will solve just equality of two objects not more.
-
Java doesn't implicitly call
hashCode
for the default implementation ofequals
. It verifies two objects point to the same reference using==
. You can havehashCode
return a random value on every call and the default implementation ofequals
will still work if you point to the same object.Marc Baumbach– Marc Baumbach2013年02月08日 20:52:50 +00:00Commented Feb 8, 2013 at 20:52 -
Your statement about checking equality by hashCode() is actually incorrect. Same hash code doesn't guarantee you equality.ATrubka– ATrubka2013年02月08日 20:53:54 +00:00Commented Feb 8, 2013 at 20:53
-
Yes Mark you are right it checks references. ATrubka,in my answer I especially specified that default implementation of Object class will be used for my example. The other possibilities not specified in my answer.emin– emin2013年02月08日 21:02:04 +00:00Commented Feb 8, 2013 at 21:02
General:
only override those methods which you want to use in your own way and also those methods which are affected by this overriding.
Specific to your Ques:
From java docs,
Note that it is generally necessary to override the hashCode method whenever equals() method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
-
That is generally true, but equals and hashcode are really meant to be consistent: overriding none or both is the default choice, making them inconsistent (overriding only one of them) is an important design decision.assylias– assylias2013年02月08日 20:41:24 +00:00Commented Feb 8, 2013 at 20:41
-
i think now i make some sense in my ans.Arpit– Arpit2013年02月08日 20:43:13 +00:00Commented Feb 8, 2013 at 20:43