Tuesday, January 1, 2013

Comparing Objects in Java

In real world, we tend to compare everything around us. Mom's car is smaller than my car. His Xbox has more memory than my Xbox. He is more higher than me. In Object Oriented language like Java we can define our own logic to compare objects.

In Java, every class extends implicitly extends from Object class. There various ways of comparing objects, they are

 ==

'==' is used between reference variable. eg: { (a==b) , (a!=b) }
It compares only the references of the two variable, and returns true if they are same and returns false if they are different.
It does not compare the values of the objects.
It may be used for comparing two enum values. This works because there is only one object for each enum constant.
But in our real life scenario we may not need to compare objects only by checking reference, we might have to check based on business logic too.

In order to perform comparison between them we need to be able to compare objects based on the criteria  we need to compare them.

equals()

'equals' method is a instance method that is available for every class since they all extends from Object implicitly.
It can be used to check values for equality in classes, but however it doesn't perform any intelligent operation unless the class override this function. If not overridden it just checks the reference of the two Objects and returns true if they are same and false it they are not.
But if you want to implement equality based on logical way or a bussiness logic, JAVA requires us to override both equals and hashcode method.

In addition to this the object equal method has to satify the following properties too,

1) Reflexive : Any object must be equal to itself.
2) Symmetric : If a.equals(b) is true then b.equals(a) must also be true.
3) Transitive : If a.equals(b) is true and b.equals(c) is true then c.equals(a) must also be true.
4) Consistent : multiple invocation of equals() method must result same value until any of properties are modified. So if two objects are equals in Java they will remain equals until any of there property is modified.
5) Null comparison : comparing any object to null must be false and should not result in NullPointerException. For example a.equals(null) must be false

The contract between equals and hashcode method states that
1) If two objects are equal, then their hashcode should be the same
2) If two objects have the same hashcode, they may be equal or different

This contract has to be honored when overriding the equal method of custom classes with our own logic.

Usage:

-Used extensively in Java core library like they are used while inserting and retrieving Object in HashMap
-To avoid duplicates on HashSet and other Set implementation
-Whenever we need to compare objects

Comparable<T> interface

The Comparable interface is used for classes that have a natural ordering. Since helps us to order elements, it greatly used for sorting. It will allow us to compare values and tell us if they are less than, equal to or grater than the other value, thus making a class comparable.

In order to implement this, the class has to implement the Comparable<T> interface and define the method CompareTo(Object o). The method returns a int value of 0,negative or positive integer based on whether the value is less,equal or greater. The method any object as parameter to compare, but me make sure we do not compare unrelated objects like we can't compare a person with a bike. 

Usage:

- Sorting of strings in array can be done simply by java.util.Array's sort method 
- Sorting of strings in collections such as ArrayList can be done by java.util.Collection's sort method
- But if we have a custom defined class such as person which we need to sort we cannot do so with either java.util.Array's sort and java.util.collection's sort. We need to implement Comparable interface and defince the CompareTo(Object o) method in the class. Then we can use either of the sort method based on the data structure we store our values in. 

Comparator interface

 Often we may have to compare objects on different basis, so having just one CompareTo(Object o) may not suffice. For example, if we have a person class we could have comparison based on
(i) age
(ii)first name
(iii)lastname
This means we might need different comaparing functions. This could be achieved with the Comparator interface which is used to compare the value of two objects in many ways.
In order to create many version of the comparing functions we need to write class that implement Comparator interface and define the compare method which has the following signature

public int compare(Object o1,Object o2) 

The method returns negative or 0 or positive number based on whether the objects is less,equal or greater than the other.

Once these classes have been defined based on unique comparing logic, we can use them in our java.util.Array's and java.util.Collections's sort method

Array.sort( <array>, <comparator_class>)

Note:If your class have only one way of sorting like number, you may not need this.

Usage:

- Allows us to define multiple ways of comparing objects. eg: age,firstname, lastname
   Arrays.sort(persons, new LastNameComparator());
   Arrays.sort(persons, new FirstNameComparator());
   Arrays.sort(persons, new AgeComparator());
- Also used for providing comparator classes to methods that we have no control over, ex: If we wanted compare strings based on their length, we could write our own custom comparator and pass it to
   Array.sort( <string>, <string_length_comparator>) 
- Very useful in Strategy Design Pattern, where we store different algorithms as different objects, that can be used later on based on the situation.



Common errors:

When comparing two objects you should know when to use to == and equals.

Equals - Objects can be different but the properties are same (Values are same)
     == -      Objects are same [ both refer to same object in memory ]


Reference-

No comments:

Post a Comment