jump to navigation

Why must implement Object.Hashcode along with Object.Equals October 26, 2009

Posted by metalickl in Software Insights.
Tags: ,
add a comment

I’ve heard of this advice over and over from various sources, and never been able to fully understand why. Until recently (few weeks ago), I was working with various java.util.Collection classes, there were a few connection made relating to this.

Whenever you get an Objects from hash based collections, such as HashMap, with a String or Integer key, you could simply say map.get(“key”) or map.get(new String(“key”)). This is because Strings or Integers are logical equivalent, which is a greater set than traditional identity equivalence (==). This allows greater flexibility to retrieve stored content from our little hash locker by playing the Keymaker, and constructing a key that is identical to the original one (in our case, a new String with the same characters).

But you cannot do this with entity objects. By default implementation, their Object.equals(Object o) simply returns this==o. This means you can never retrieve the stored content with any other object beside the one you’ve used in Map.put(Object key, Object value).

Hash based collections simply uses the hash code to identify a smaller, refined group of stored objects from the larger collection. If you’ve modified Object.equals to allow both identity and logical equivalence, but not Object.hashcode. Then try to search the collection with the logically equivalent key (same colour, same groove, but just not the key you’ve used the first time!), then obviously the hash based collection, who relies only on Object.hashcode to refine the search will have no idea that this Type is also logically equivalent. In this case, its attempt to refine the collection fails with false precondition.

—–

May be off topic, but then you would think an easy way to implement equals (for both identity and logical equivalence) along with hashcode would be simply compare the string representation of the 2 Objects (including instance members in some way or the other) and just output the hashcode of the string representation of the Object. This saves you the time (mostly brain power) to implement the non-trivial hash functions. This is acceptable, but not performance efficient or easy to read.

This is why it’s always nice to override Object.toString() ;)

—–

Btw, Object serialization does preserve identity equivalence, IF:

  1. Both a and b are written as and subsequently read from as parts of the same stream. Here’s a quote from ObjectInputStream documentation: “Graphs of objects are restored correctly using a reference sharing mechanism.”
  2. Class of a and b does not override readResolve() that has the potential of changing how references are restored back; neither do classes that hold a and b.

For all other cases, object identity will NOT be preserved.

A fresh start October 18, 2009

Posted by metalickl in Life.
add a comment

Haven’t been blogging at all for the past two years. Time for a fresh start. So much have changed and it’s also a time to change the focus of the blog. I will be posting more interesting things in software engineering and music.