• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Override only hashcode but not equals.

 
Ranch Hand
Posts: 42
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello all, I'm studying the contract between hashcode and equals, and thinking of possible problems that may occur in case only one is overriden. So there are two cases :
1. Override equals only.
2. Override hashcode only.

For the first one, I'm quite clear that overriding equals only will break the contract since logically equal objects will have different hashcodes.
But the second part is a bit confusing. If I only override hashcode (though I know this won't benefit me at all in any scenario), I don't think it violates any of the 3 points mentioned in the contract. Please correct me if I'm wrong.
 
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No. The requirement is that it's consistent. That means that if you override hashCode() to return anything that's based on state that isn't used by equals(), you've violated the contract. Let's take the following example:

We haven't overridden equals(), so this means that two copies of a book with the same ISBN are different books. This also means that the book should always return the same hash code. However, if we take a copy of a book and change its ISBN, the book will still be equal to itself, but its hash code will have changed. This violates the hashCode() contract.
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So in general, hashCode() may only use state that's used by equals(). It is allowed to use less state. When you don't override equals(), the identity of the object is the state that's used. Valid return values for hashCode() are based on the state (for instance, the memory address of the object), or less (for instance, returning a constant).

Returning a constant is always valid, but never advisable.
 
Brendon McCullum
Ranch Hand
Posts: 42
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Stephen : I agree on all points that you mentioned, and the example also makes sense. I have a doubt though. In your example, you change the isbn of the book, but the object remains the same (as reference is same), but what about in case I change isbn to final (just like String class). How'd it violate the contract then? Thanks.
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It wouldn't. It's also useless, because the new hash code implementation does nothing better than the original. In fact, it's worse because many different books may have the same hash code.

Yes, it's possible to override only hashCode() without violating its contract. Yes, it's also possible to override only equals() without violating the contract. Are any of these cases meaningful? No.
 
Brendon McCullum
Ranch Hand
Posts: 42
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Stephen : Thanks for clearing it out.
 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Brendon McCullum wrote:For the first one, I'm quite clear that overriding equals only will break the contract since logically equal objects will have different hashcodes.


Yes, but is that a violation of equals() or hashCode()?

But the second part is a bit confusing. If I only override hashcode (though I know this won't benefit me at all in any scenario), I don't think it violates any of the 3 points mentioned in the contract. Please correct me if I'm wrong.


No, you're not wrong, unless you implement it in such a way that it could return a different hash code when two objects are equal; which is why:
  public final int hashCode() { return 17; }
is ALWAYS valid.

However, it offers nothing that Object.hashCode() doesn't already, and is absolutely horrible, performance-wise, for hashed datasets.

Winston
 
Marshal
Posts: 79180
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Afraid it does violate the general contract of hashCode. It says the hash code should remain unchanged as long as no information used by equals changes. If you change ISBN and don't use it in equals, you are changing the hash code. It's all in the Object#hashCode documentation.
 
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:No, you're not wrong, unless you implement it in such a way that it could return a different hash code when two objects are equal; which is why:
  public final int hashCode() { return 17; }
is ALWAYS valid.


No it's not, it should be 42

However, it offers nothing that Object.hashCode() doesn't already, and is absolutely horrible, performance-wise, for hashed datasets.

Winston


In fact, it turns a HashSet into basically the equivalent of a LinkedList - to check for existence, the entire HashSet will need to be traversed until a match is found.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Afraid it does violate the general contract of hashCode. It says the hash code should remain unchanged as long as no information used by equals changes.


Which means that Object.hashCode(), by default, violates its own principle.

Why not just say it outright: if you implement equals(), you MUST implement hashCode(), and NOW here are the rules....

Winston
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:. . . Object.hashCode(), by default, violates its own principle.

No, it doesn't. It returns the same result as a default

Why not just say it outright: if you implement equals(), you MUST implement hashCode(), and NOW here are the rules....

Winston

That would be too easy.

The Object#equals documentation wrote:it is generally necessary to override the hashCode method whenever this method is overridden

It says that elsewhere.
 
reply
    Bookmark Topic Watch Topic
  • New Topic