Wednesday Aug 07

Hashcode and Equals

Hashcode and Equals

AddThis Social Bookmark Button

HashCode and Equals

HashCode

The hashcode method is inherited from the great grandparent of all classes Object, thus an instance of any object can make a call to hashcode. The signature of hashcode is

 public int hashCode(){}; 

Thus you might get an exam question that offers you some bogus signatures for hashcode that return types other than int or take some parameters instead of none. However I suspect the questions tend to be slightly more theoretical than this.

The int value that is returned is of particular use with the hash based Collection classes, ie

HashTable, HashSet, HashSet

The nature of hash based collections is to store keys and values. The key is what you use to look up a value. Thus you could for instance use a HashMap to store employee id in the key value and the employee name in the value part.

Generally a hashcode value will be the memory address of the object. You can demonstrate this to yourself quite easily with some trivial code such as.

The integer returned is a representation of the memory address of that class on that run of the program. This illustrates one of the features of a hashcode is that it does not have to be the same value from one run of a program to another. If you think about the memory address of an object there is not guarantee at all what it will be from one run to another of a program.

Here is a quote from the JDK1.4 docs that covers this part of the requirements for a hashcode value.

“Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.”

Note how it says that the value returned from hashCode must be the same in the same program run provided no information used in the equals method comparisons on the object is modified. This brings us to the relationship between the equals and the hashCode method.

equals and hashCode

access to an equals method because it is inherited from the great grandparent class called Object. However this default object does not always do anything useful as by default it simply compares the memory address of the object. The downside of this can be seen dramatically when used with the String classes. If the String class did not implement its own version of the equals method comparing two Strings would compare the memory address rather than the character sequence. This is rarely what you would want, and for this reason the String class implements it's own version of the equals method that makes a character by character comparison.

Here is another of the points from the API documentation

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

When two objects are not equal

It would be a plausible extrapolation from what I have covered so far to believe that two objects that are not equal according to the equals() method would have to return different hashCode values. This is not so, as stated in the API docs.

Objects that are equal according to the equals method must return the same hashCode value

It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing

If two objects are not equal according to equals, they are not required to return different hashCode values. It is worthwhile looking up the original API docs to understand the requirements of the hashCode method.

Implementing HashCode and Equals

The Jakarta-Commons org.apache.commons.lang.builder package is composed entirely of classes designed to help implement the base contracts of a class extending java.lang.Object - by that I specifically mean equals() ,hashCode() , and toString() . They are called builders because they provide an easy-to-use API for building results to these methods.

The HashCodeBuilder

The HashCodeBuilder is quite a bit more time-saving and helps avoid making mistakes in this commonly error-prone programming process. People struggle with implementing hashCode() , and this class simplifies it by automatically handling all of the 'modifier' details. Here is how you would implement a hashcode algorithm for our same class (adapted from the Javadocs):

Java Hashcode example

	public int hashCode() {
		 return new HashCodeBuilder(61, 15)
		 	.appendSuper(super.hashCode())
		 	.append(firstName)
			.append(lastName)
			.toHashCode();
	}

This is remarkably similar looking to the equals builder. Note that the two numbers for the constructor are simply two different, non-zero, odd numbers - these numbers help to avoid collisions in the hashcode value across objects.

Alternatively, as with the equals builder, there is a reflection option (with the same drawbacks):

Java Hashcode using Reflection

 public int hashCode() {
   return HashCodeBuilder.reflectionHashCode(this);
 }

The ToStringBuilder

This is my personal favorite builder (the toString() builder) - primarily because it has the most flexibility, and is also implementing a feature that is typically used for debugging, so performance isn't as critical of a concern. This builder is just like the other ones in its base form:

Java tutorial toString example

	public String toString(){
		 return new ToStringBuilder(this)
			 .appendSuper(super.toString())
			 .append("first name", firstName)
			 .append("last name", lastName)
			 .toString();
	}


In addition, this builder also has the reflection option:

Java toString using Reflection

 public String toString() {
   return ToStringBuilder.reflectionToString(this);
   // May also use ReflectionToStringBuilder.toString(this)
 }

If you wish, you can extend the ToStringStyle class, and pass it in to the builder. There are quite a few methods, and they're all pretty straightforward - I personally find, however, that the standard style works perfectly fine in most cases.

The CompareToBuilder

While I didn't mention it earlier, there is one additional builder in this package - the CompareToBuilder. it follows allong in the exact same lines as the other builders (no surprise):

CompareToBuilder example

	public int compareTo(Person person) {
		return new CompareToBuilder()
		       .append(this.firstName, person.firstName)
		       .append(this.lastName, person.firstName)
		       .toComparison();
	}

... and yes, there is yet another reflection option:
Java compare example

 public int compareTo(Object o) {
   return CompareToBuilder.reflectionCompare(this, o);
 }

View other articles about Core Java features

Other interesting Java tutorial

Tags: method , hashcode , equals , objects , class

Add comment


Security code
Refresh

Java Tutorial on Facebook