Showing posts with label equals. Show all posts
Showing posts with label equals. Show all posts

Thursday, June 12, 2008

Implementing Equals and HashCode

In my last blog i described how we can compare two java objects of same class by overriding equals method. In this blog i will explain best practices regarding implementing of equals method.
Whenever, we go for overriding of equals method, one question comes to our mind is, on which basis we will have to say that two objects are same. First answer comes to mind is that we should compare objects on the basis of primary key which is also used to distinguish the records in the database. Primary keys are good candidate to compare objects if we assign primary keys ourself not by database. When primary key is assigned by database like auto number, objects don't have primary key until they are persisted in the database so before persistent of objects, how we should compare the objects. Good practice is always compare objects on the basis of business key which uniquely describes objects. Suppose we have a class of Person with attributes (id, name, ssn,address) . In this class we have two unique attributes one is id and second one is ssn. id is used to distinguish the objects in the database and is assigned when objects are persisted, then only choice is SSN which we can use to compare different person because each person has his own SSN (Social Security Number). So best practice is always compare objects on business keys rather than on database keys.
Second best practice is whenever you go for overriding of equals method. also override "int hashCode()" method. This method returns hash of objects. Implementing hasCode facilitates us when we use objects as keys in HashTable. If we don't override hashCode method, each object created with new operator will always has different hash values irrespective of fact whether they are same or not. Suppose I have a class of Customer with attributes (id, name, ssn, address) and i create two objects with new operation having the same dataset. Although logically they are same but physically they are two different objects that's y they have differnt hashCode. So best practice is that if two objects are equals, then those two objects should always have same hashCode. Overriding of hashCode will also facilitate us when we save objects in sets. Sets store only one instance of an object at a time, so if we have two customer objects with same attributes, then only one instance of customer must be saved in sets. It is only possible by overriding of hashcode method.
Now question is how to generate hashCode for an object. Answer is same as for equals method. Always generate hashCode from business keys. In above example of Customer objects, we should generate hashCode of Customer from SSN. java has provided methods which generate hashCode for all primitive data types and for String. hashCode for primitive data types are generated by using wrappers of primitive data types e.g. for int we can generate hashCode by following code:

Integer i = new Integer(5);
int code = i.hashCode();

Similary we can get hashCode of other primitive datatypes by using respective wrapper classes.

So in this blog we have come to Two Best Practices regarding comparison of objects:
- One is always compare objects in equal method on the basis of business keys.
- Second is whenever override equals method, also override hashCode method and generate hash for objects on the basis of same business key as used in equals method.

Saturday, May 3, 2008

Comparison of Objects with equals

== relational operator is used to compare basic data types in java e.g. if we want to compare two integers, we will do it as follows:

int a = 5;
int b = 5;
if (a == b)
System.out.println("equal");
else
System.out.println("not equal");

Output of above java code will be "equal". but this "==" operator works only with basic data types, even it will not work if we use wrapper classes of basic data types e.g.

Integer a = new Integer(5);
Integer b = new Integer(5);
if (a == b)
System.out.println("equal");
else
System.out.println("not equal");


Output of above code will be "not equal". Why "==" operator does not applicable for objects is that because it compares two references of object not contents of objects. Now for comparison of contents of objects there is "equals" method in each object e.g. if we change above comparison of wrapper classes with this code, it will work correctly:

Integer a = new Integer(5);
Integer b = new Integer(5);
if (a.equals(b))

System.out.println("equal");
else
System.out.println("not equal");

Output of above code will be "equal" This "equals" work fine for wrapper classes but does not run correctly for custom classes because it compares two object references by default just like "==" operator. To change behaviour of "equals" we will have to override it in our classes. Suppose i have a class "Book" which has attributes like name, isbn, author, publisher. Now uniqueness of book is checked using isbn number so to compare two books, override "equals" method and in that implementation check the "isbn" of book. Code Structure is given below:

public class Book{
private String isbn;
private String name;
private String author;

public String getIsbn() {
return isbn;
}

public void setIsbn(String isbn) {
this.isbn = isbn;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAuthor() {
return author;
}

public void setAuthor(String author) {
this.author = author;
}

@Override
public boolean equals(Object obj) {
Book book = (Book)obj;
if (this.isbn.equals(book.getIsbn()))
return true;

return false;
}

public static void main(String args[]) {
Book b1 = new Book();
b1.setName("Java");
b1.setAuthor("Amer");
b1.setIsbn("12334");
Book b2 = new Book();
b2.setName("Java");
b2.setAuthor("Amer");
b2.setIsbn("12334");
if (b1.equals(b2))
System.out.println("equal");
else
System.out.println(" not equal");
}
}

output of above code will be equal. even if name or author of two are different because my implementation of "equals" just checks for "isbn".

In my later post, i will exlain best practices related to overriding of "equals" method.