Posts Tagged ‘equals and hashcode example in java’

equals & hashcode methods in Java

January 7, 2011

Java Object class allows you to override equals & hashcode methods based on your application requirements. These methods play an essential role in real time applications.

You must have to implement these two methods when objects are stored into collections. Suppose if you are failed to implement or implemented incorrectly then the collections may behave strangely and hard to debug.

Methods have certain principles & contracts to follow while overriding.

public boolean equals(Object obj)

  • Used for comparison between two objects i.e., check whether the passing parameter object is equal to current object.
  • It has some principles to follow for non-null object references, they are reflexing, symmetric, transitive, consistent, null comparison.

public int hashCode()

  • Returns the hashcode of an object, its an integer value of object memory address.
  • This technique is called hashing used to efficiently store and retrieve the enormous data in the collections like Hashtable, HashSet, HashMap.

You can read elaborate description @ java api doc

The most significant contract between equals & hashcode is

If two objects are equal then they must have the same hashcode, however the reverse is not true.

If two objects have the same hashcode does not mean that they are equal.

Note

  • If you override equals method in the class, you must override the hashcode also.
  • If a field is not used in equals(), then it must not be used in hashcode() method.

In the BookStore app, the class Book has two fields bookName & authorName both of them were used in equals & hashcode method to identify the two objects are equivalent. However the following implementation is wrong.

Field bookName only used to identify the equality

public boolean equals(Object obj) {

…..

…..

Book bobj = (Book) obj;

if (bookName == bobj.bookName || (bookName != null && bookName.equals(bobj.bookName))) {

return true;

}

}

return false;

}

Both fields bookName & authorName were used to manipulate hashcode.

public int hashCode() {

int hash = 7;

hash = (37 * hash) + (null == bookName ? 0 : bookName.hashCode());

hash = (37 * hash) + (null == authorName ? 0 : authorName.hashCode());

return hash;

}

Lets see how to override methods in our simple BookStore app.

EqualsHashCodeBookApp.java

Stored the instances of Book class into the collection List and properly implemented the equals & hashcode method to retrieve the correct object data from the List.

import java.util.ArrayList;
import java.util.List;

 class Book {

 String bookName;
 String authorName;

 Book() {
 }

 Book(String bookName, String authorName) {
 this.bookName = bookName;
 this.authorName = authorName;
 }

 @Override
 public boolean equals(Object obj) {
 if (this == obj) {
 return true;
 }

 if (obj == null || (obj.getClass() != this.getClass())) {
 return false;
 }

 Book bobj = (Book) obj;
 if (bookName == bobj.bookName || (bookName != null && bookName.equals(bobj.bookName))) {
 if (authorName == bobj.authorName || (authorName != null && authorName.equals(bobj.authorName))) {
 return true;
 }
 }
 return false;
 }

 @Override
 public int hashCode() {
 int hash = 7;
 hash = (37 * hash) + (null == bookName ? 0 : bookName.hashCode());
 hash = (37 * hash) + (null == authorName ? 0 : authorName.hashCode());
 return hash;
 }

 @Override
 public String toString() {
 StringBuffer sb = new StringBuffer();
 sb.append("bookName=").append(bookName);
 sb.append(",authorName=").append(authorName);
 return sb.toString();
 }
 }

 public class EqualsHashCodeBookApp {

 public static void main(String a[]) {
 Book b1 = new Book("C Programming", "Dennis Ritchie");
 Book b2 = new Book("C++", "Stroustroup");
 Book b3 = new Book("Java", "James Gosling");
 Book b4 = new Book("JavaScript", "Douglas Crockford");
 Book b5 = new Book("OOAD", "Grady Booch");


 boolean b1eqb1 = b1.equals(b1);
 boolean b1eqb2 = b1.equals(b2);
 boolean b2eqnewobj = b2.equals(new Book("C++", "Stroustroup"));
 boolean b1eqnull = b1.equals(null);

 System.out.println("Object b1 equals b1 :: " + b1eqb1);
 System.out.println("Object b1 equals Object b2 :: " + b1eqb2);
 System.out.println("Object b2 equals new Book(\"C++\", \"Stroustroup\") :: " + b2eqnewobj);
 System.out.println("Object b1 equals null :: " + b1eqnull);

 List<Book> list = new ArrayList<Book>();
 list.add(b1);
 list.add(b2);
 list.add(b3);
 list.add(b4);
 list.add(b5);
 System.out.println("List of books : " + list);
 System.out.println("List of books : " + list.size());
 System.out.println("Hashcode of object b1 : " + b1.hashCode());
 System.out.println("System Hashcode of object b1 : " + System.identityHashCode(b1));
 //check whether this book is available in the list.
 boolean b = list.contains(new Book("Java", "James Gosling"));
 System.out.println("Book new Book(\"Java\", \"James Gosling\") : " + b);
 System.out.println("Index of Book(\"Java Programming\", \"James Gosling\") : " + list.indexOf(new Book("Java Programming", "James Gosling")));
 System.out.println("Index of object b3 : " + list.indexOf(b3));
 }
 }

Output

Object b1 equals b1 :: true

Object b1 equals Object b2 :: false

Object b2 equals new Book(“C++”, “Stroustroup”) :: true

Object b1 equals null :: false

List of books : [bookName=C Programming,authorName=Dennis Ritchie, bookName=C++,authorName=Stroustroup, bookName=Java,authorName=James Gosling, bookName=JavaScript,authorName=Douglas Crockford, bookName=OOAD,authorName=Grady Booch]

Hashcode of object b1 : 649340260

System Hashcode of object b1 : 1671711

Book new Book(“Java”, “James Gosling”) : true

Index of Book(“Java Programming”, “James Gosling”) : -1

Index of object b3 : 2

Overridden equals & hashcode method will get invoked while executing the below lines to verify the equivalent object data is present in the collection list.

list.contains(new Book(“Java”, “James Gosling”));

list.indexOf(new Book(“Java Programming”, “James Gosling”)

Returns the hashcode value from the overridden method.

b1.hashCode();

Returns the system hashcode value. i.e., actual memory address of an object

System.identityHashCode(b1);