Showing posts with label Equals. Show all posts
Showing posts with label Equals. Show all posts
Points To Remember
  • equals(), method is a method of the Object class, hence is available in all classes.
  • Syntax of equals in Object class is public boolean equals(Object obj).
  • It return true if two objects are same, in object class it just checks if the two references points to the same class. 
  • We can override the equals method to provide custom logic to say the two objects are same. See How to override equals method
Concept: Making two objects same.
Suppose we have a Book class and each object represents a book. We create three objects book1, book2 and book3 (new keyword always creates a new object) and the objects book1, book2 refer to same book same with name 'Think Think' and id '1', book 3 refers to book 'Bad Kitty'. So in real case scenario the book1 and book2 objects should be same or equal.
id=1, name = Think Think 
id=2, name= Bad Kitty












So lets check how many objects are created and if they are equal when their member variables are same. (According to our case, objects with same id and name should be equal)
class Book{
int id;
String name;
public Book(int id, String name){
this.id = id;
this.name= name;
}
}

class Test{
public static void main(String args[]){
Book book1 = new Book(1,"Think Think");
Book book2 = new Book(1,"Think Think");
Book book3 = new Book(2,"Bad Kitty");

System.out.println("book1.equals(book2) = "+ book1.equals(book2));
System.out.println("book1.equals(book3) = "+ book1.equals(book3));
System.out.println("book2.equals(book3) = "+ book2.equals(book3));
}
}
book1.equals(book2) = false
book1.equals(book3) = false
book2.equals(book3) = true
The above output proves that there are only 2 objects created, one for book1, and other for book2, book3 shares the object of book2.

But we may want to make objects book1 and book2 as same since they represents the same book (they have same book id and book name ). So we need to do some thing to make all the book objects that have same id and name as same objects or equal objects.

What we need to do is, override equals and hashcode methods of the Object class. The following program shows how we can say the two objects with same id and name are equal.
class Book{
int id;
String name;

public Book(int id, String name){
this.id = id;
this.name= name;
}

@Override
public boolean equals(Object obj){
// Null checks not included.
Book book = (Book)obj;
if(this.name.compareTo(book.name)==0 && this.id == book.id)
return true;
else
return false;
}

@Override
public int hashCode(){
return this.name.hashCode() * this.id;
}
}

class Test{
public static void main(String args[]){
Book book1 = new Book(1,"Think Think");
Book book2 = new Book(1,"Think Think");
Book book3 = new Book(2,"Bad Kitty");
System.out.println("book1.equals(book2) = "+ book1.equals(book2));
System.out.println("book1.equals(book3) = "+ book1.equals(book3));
System.out.println("book2.equals(book3) = "+ book2.equals(book3));
}
}
book1.equals(book2) = true
book1.equals(book3) = false
book2.equals(book3) = false
The objects with reference book1 and book2 are equal since according to our custom logic, book object with same id and name must be equal. Also do read the contract between hashCode() and equals() method.
Points To Remember
  • Both the method equals() and hashCode() are the methods of Object class, hence available in all the classes.
  • Syntax for equals() method in Object class is public boolean equals(Object obj)
  • Syntax for hashCode() method in Object class is public int hashCode()
  • The equals() method of Object class checks if the two references compared point to same object, returns true if they are same and false if two objects are different. We can override this functionality by our own custom way of comparing objects.
  • If the equals() method returns true, then the hashcode() of the two object must be same.
  • If hashCode() of two objects are same, it does not mean that the objects should be same.
Concept : equals() & hashCode() method in Object class 
First of all lets see what does an equals() method do in java. The equals method in the object class is used to see that if the two object references are pointing to the same object. See how equals() method works. So if two references are pointing to same object then all the member variables of the object must be same in all respect, this means that the hashcode of the two  objects must also be same.

Let us see How hashCode() method works. The hash code method returns the hash a 16 digit integer number from some internal hashing algorithm.
This is a one way process, which means
  • if we know a key then we can generate the hashcode and it will always be the same
  • but if we have hashcode, then we cannot find the key from hashcode.
where key can be any object that needs to be hashed.

So, we summarize as below.
  1. If equals returns true, then the hashcode of the two objects must be same.
  2. If equals returns false, hashcode may or may not be same.
  3. If hashcode of two objects is same, then equals may may not return true.
Program : Invalid use of hashCode() and equals()
The below program as a problem, it does not follow the contract of equals and hashcode.We override the equals method and say that the two object of Book class are equal if their name is same. So by convention,  if the name of two books are same then the hashcode of objects must be same. But in this case the hashcode may vary since we multiply the hashcode of book name with book id, where book id may be different.
class Book{
int id;
String name;

public Book(int id, String name){
this.id = id;
this.name= name;
}

@Override
public boolean equals(Object obj){
// Null checks not included.
Book book = (Book)obj;
if(this.name.compareTo(book.name)==0 )
return true;
else
return false;
}

@Override
public int hashCode(){
return this.name.hashCode() * this.id;
}
}

class Test{
public static void main(String args[]){
Book book1 = new Book(1,"book");
Book book2 = new Book(2,"book");
Book book3 = new Book(1,"book");
System.out.println("book1.equals(book2) = "+ book1.equals(book2) + " book1.hash= "+book1.hashCode()+ " book2.hash= "+book2.hashCode());
System.out.println("book1.equals(book3) = "+ book1.equals(book3) + " book1.hash= "+book1.hashCode()+ " book3.hash= "+book3.hashCode());
System.out.println("book2.equals(book3) = "+ book2.equals(book3) + " book2.hash= "+book2.hashCode()+ " book3.hash= "+book3.hashCode());
}
}
book1.equals(book2) = true book1.hash= 3029737 book2.hash= 6059474
book1.equals(book3) = true book1.hash= 3029737 book3.hash= 3029737
book2.equals(book3) = true book2.hash= 6059474 book3.hash= 3029737
Program : Valid use of hashCode() and equals()
In the above example the problem was that, the two objects that are same according to our implementation should also have returned same hashcode, but it was not so(as shown by the output). So we may correct this by either
  • changing this.name.hashCode() * this.id;  to this.name.hashCode();
  • changing if(this.name.compareTo(book.name)==0 ) to if(this.name.compareTo(book.name)==0 && this.id == book.id)
class Book{
int id;
String name;

public Book(int id, String name){
this.id = id;
this.name= name;
}

@Override
public boolean equals(Object obj){
// Null checks not included.
Book book = (Book)obj;
if(this.name.compareTo(book.name)==0 && this.id == book.id)
return true;
else
return false;
}

@Override
public int hashCode(){
return this.name.hashCode() * this.id;
}
}

class Test{
public static void main(String args[]){
Book book1 = new Book(1,"book");
Book book2 = new Book(2,"book");
Book book3 = new Book(1,"book");
System.out.println("book1.equals(book2) = "+ book1.equals(book2) + " book1.hash= "+book1.hashCode()+ " book2.hash= "+book2.hashCode());
System.out.println("book1.equals(book3) = "+ book1.equals(book3) + " book1.hash= "+book1.hashCode()+ " book3.hash= "+book3.hashCode());
System.out.println("book2.equals(book3) = "+ book2.equals(book3) + " book2.hash= "+book2.hashCode()+ " book3.hash= "+book3.hashCode());
}
}
book1.equals(book2) = false book1.hash= 3029737 book2.hash= 6059474
book1.equals(book3) = true book1.hash= 3029737 book3.hash= 3029737
book2.equals(book3) = false book2.hash= 6059474 book3.hash= 3029737