Rajinder Menu

Defensive Copy Part 2: Defensive Copy using Copy Constructors






I would like to know your comments and if you liked the article then please share it on social networking buttons.


Defensive Copy Part 1: The problem and The solution.







I would like to know your comments and if you liked the article then please share it on social networking buttons.


Object copying in java using Copy Constructor







I would like to know your comments and if you liked the article then please share it on social networking buttons.




You may like to read:
How to write a Copy Constructor using Copy Constructor.
How to write a Copy Constructor using Deep copy.
Copying Object by shallow Copy.
Copying Object by deep copy.

Object Copying in java using Deep Copy






I would like to know your comments and if you liked the article then please share it on social networking buttons.




You may like to read:
How to write a Copy Constructor using Deep copy.
How to write a Copy Constructor using Copy Constructor.
Copying Object by shallow Copy.
Copying Object by Copy Constructors.

Object Copying in java using Shallow Copy






I would like to know your comments and if you liked the article then please share it on social networking buttons.




You may like to read:
How to write a Copy Constructor using Deep copy.
How to write a Copy Constructor using Copy Constructor.
Copying Object by deep copy.
Copying Object by Copy Constructors. 

Using Comparable interface to compare objects of two different types.



Comparable interface and its compareTo() method is generally used to compare objects in their natural order and for comparing instances of same class.

But this is not a restriction, only a guideline set by contract of Comparable.  We can still write code that compares objects of two different types using compareTo() as shown below:

MyClass.java
public class MyClass implements Comparable<String>{

  int i;
  public MyClass(int i){
    this.i=i;
 }

  /*
   Here we are using compareTo() to compare objects of two different types - MyClass (represented by 'this') and String.
 */
 @Override
 public int compareTo(String str){
   int intValue=Integer.parseInt(str);

  if(this.i > intValue)
     return 1;
  if (this.i < intValue)
     return -1;
  else
    return 0;
 }
}

Test.java
public class Test{
public static void main(String args[]){

   MyClass myClass= new MyClass(1);

/*Using compareTo() to compare objects of two different types - MyClass and String.*/
  if(myClass.compareTo("10")<0)
      System.out.println("myClass is smaller.");
else if(myClass.compareTo("10")>0)
     System.out.println("myClass is greater.");
else if(myClass.compareTo("10")==0)
    System.out.println("Both equals!!!");
  }
}


Here in compareTo() method of MyClass, we are comparing two objects - one of type MyClass and other of type String with output:


Also there is no natural order between MyClass and String instances as natural order exists between the objects of same type.

Usually we throw ClassCastException in compareTo() when we do not want to it to compare objects of different types as:


public class MyClass implements Comparable<String>{
..
public int compareTo(String str){
...
if(!(obj instanceof MyClass)){
       throw new ClassCastException("Not Comparable Objects!");   // will throw exception
    }
}


and with the use of generic form of Comparable we even do not need to throw ClassCastException as types will be checked at compile time.


public class MyClass implements Comparable<MyClass>{
  public int compareTo(String str){  // will throw error at compile  time
   ...
 }
}




I would like to know your comments and if you liked the article then please share it on social networking buttons.


Sorting based on multiple attributes of a Class.



In the Comparable and Comparator- part 1, 2, 3 and 4 you have seen sorting based on single attribute of a class but you may also need to sort elements based on more than one attribute.  For example if we take Book class :

public class Book{
  String title;
  String author;
  double price;
  String publisher;
  ...
}

You may need to sort books according to their authors first, then within each author books should be sorted based on their title, and within each title they should be sorted according to their price.

Lets see how to do this.

Book.java
public class Book implements Comparable<Book>{

   String title;
   String author;
   double price;
   String publisher;

     public void setTitle(String title){
       this.title=title;
     }

    public String getTitle(){
      return title;
    }

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

   public String getAuthor(){
    return author;
   }

   public void setPrice(double price){
    this.price=price;
   }

   public double getPrice(){
   return price;
   }

   public void setPublisher(String publisher){
    this.publisher=publisher;
  }

  public String getPublisher(){
   return publisher;
  }

public int compareTo(Book book){

     if(book == null){
       throw new NullPointerException("Book passed is null!");
    }

    if(this.getAuthor().equals(book.getAuthor())){  /*Most significant field*/
      
     if(this.getTitle().equals(book.getTitle()))   /*Next Most significant field*/
            return (int)(this.getPrice()-book.getPrice());
          else
           return this.getTitle().compareTo(book.getTitle());
     }
     else
          return this.getAuthor().compareTo(book.getAuthor());
      
  }
}

BookComparision.java
import java.util.Arrays;

public class BookComparision{
  
    public static void main(String args[]){
      
        Book book1 = new Book();       
        book1.setAuthor("Author A");
        book1.setTitle("Title B");
        book1.setPrice(225.00);
       
        Book book2 = new Book();       
        book2.setAuthor("Author A");
        book2.setTitle("Title B");
        book2.setPrice(125.00);
       
       
        Book book3 = new Book();       
        book3.setAuthor("Author B");
        book3.setTitle("Title B");
        book3.setPrice(125.00);
       
        Book book4 = new Book();       
        book4.setAuthor("Author B");
        book4.setTitle("Title A");
        book4.setPrice(200.00);
       
       
        Book book5 = new Book();       
        book5.setAuthor("Author C");
        book5.setTitle("Title C");
        book5.setPrice(125.00);
       
        Book book6 = new Book();       
        book6.setAuthor("Author C");
        book6.setTitle("Title B");
        book6.setPrice(125.00);
       
        Book book7 = new Book();       
        book7.setAuthor("Author C");
        book7.setTitle("Title B");
        book7.setPrice(400.00);
       
       /* An array containing Books*/
        Book[] bookArray = new Book[7];
        bookArray[0]=book1;
        bookArray[1]=book2;
        bookArray[2]=book3;
        bookArray[3]=book4;
        bookArray[4]=book5;
        bookArray[5]=book6;
        bookArray[6]=book7;
       
        System.out.println("Sorted Books:");
      
        Arrays.sort(bookArray);

        for(int i=0;i<=6;i++){
        System.out.print("Author:"+bookArray[i].getAuthor()+"        ");
        System.out.print("Title:"+bookArray[i].getTitle()+"        ");
        System.out.println("Price:"+bookArray[i].getPrice());

        }       
   }
 }

Output:

Sorted Books:
Author:Author A         Title:Title B           Price:125.0
Author:Author A         Title:Title B           Price:225.0
Author:Author B         Title:Title A           Price:200.0
Author:Author B         Title:Title B           Price:125.0
Author:Author C         Title:Title B           Price:125.0
Author:Author C         Title:Title B           Price:400.0
Author:Author C         Title:Title C           Price:125.0


When your comparision is based on multiple attributes, remember to on compare most significant attribute first. Which attribute is most significant it depends on you. Here we are assuming author as our most significant attribute.

When most significant attribute is equal then only go for comparing next most significant field, otherwise return the integer as shown below:


if(this.getAuthor().equals(book.getAuthor())){
       
 // check next most significant field
}
else
  return this.getAuthor().compareTo(book.getAuthor());





I would like to know your comments and if you liked the article then please share it on social networking buttons.


When to use Comparable and Comparator in java?


Now from part 1, 2, 3 and 4 you have learned how to use Comparable and Comparator in java and now you also know that main purpose of both interfaces is to compare things so that we can sort them.

Often some questions are asked in interviews with respect to Comparable and Comparator like:

1) When to use Comparable and When to use Comparator in java. OR

2) What is the difference between Comparable and Comparator in java? OR

3) Which is preferred Comparable or Comparator? OR

4) Why do you need Comparable if Comparator can also sort things?

5) Or interviewer may give you some class and  some criteria  and ask you to write code to sort instances of that class based on that criteria.You have to decide  whether to use Comparable or to use Comparator. or even, not to use any of them.

This article outline some of the facts which help you decide in which situations one should use Comparable and in which Comparator.

1) Code Availabilty

The first thing to note is that while using Comparable you have to implement it in your class i.e you need to change your class. Example

  public class Book implements Comparable{
   ...
  }

For this, code of that class should be availaible to you . If you dont have access to the code of that class (say class belongs to third party), then there is no choice but to use Comparator because Comparator does not need to change the original class.

2) Single Versus Multiple Sorting Criteria


If you have only single sorting criteria to sort your elements then you can use Comparable but if you have more than one sorting criterias then you have to go for Comparator also.

3) Arays.sort() and Collection.sort()

Using Comparable has a advantage over Comparator. If your class implements Comparable then Arrays.sort() and Collections.sort() can sort its instances automatically. You do not need to write separate comparators and pass them to overloaded sort() as shown here.

4) As keys in SortedMap and SortedSet

This is another advantage of Comparable over Comparator. Objects which implement Comparable interface can be used as keys in a SortedMap( like TreeMap) or as elements in a SortedSet  (like TreeSet). Otherwise you have to write separate Comparator and pass it in the constructor of TreeMap.

5) More Number of classes Versus flexibilty

Use of Comparable does not require creation of extra classes while use of Comparator requires writing of separate comparators i.e more number of classes.

But this has a advantage also.You can add as many sorting criteria later as you want or modify the existing ones without changing the class whose instances you are sorting.

 Thus comparators provides flexibilty while Comparable avoids extra classes.

Note that you can also write Comparators as anonymous classes. In that case you can avoid separate comparators also.

6) Interclass comparisions

If you are going to compare instances of same class then you should use Comparable. Though we can also compare objects of different types while using Comparable as shown here but we should avoid it.

 If you are going to compare instances of different classes then you should use Comparator. But this was valid upto  pre Java 5, before the introduction of generics.

With the introduction of generics syntax of Comparator has been changed from :

public interface Comparator  to   public interface Comparator <T>

and of compare() from:

public int compare(Object o1, Object o2)  to  public int compare(T o1,T o2)

As you are seeing in new syntax both o1 and o2 are of type T. If their types would be different as:

compare(Integer o1, String o2) 


then this will give compile time error.

Therefore if generic form of compare() is used then it compares objects of only same types.

With non generic form of compare() you can still compare objects of different types.

7) Natural Order

If you are going to sort elements according to their natural order then you should use Comparable and for any other order different from natural order Comparator should be used.


Thus to answer above given questions:-

1) When to use Comparable and When to use Comparator?

Ans:- When you are going to sort according to natural order, have single sort criteria and  have access to the class you would use Comparable.

Otherwise,

If you cannot change the class and have multiple sorting criteria use Comparator.


2) Interviewer may give you some class and  some criteria  and ask you to write code to sort instances of that class based on that criteria.You have to decide there whether to use Comparable or to use Comparator. or even, not use any of them?

Ans: For example,
If you are given a class named Employee and asked to sort it's instances by employees id, then you should go Comparable as it seems its natural order.

But if you have to sort them by its salary or Date of Joining () etc.(which does not seem to be natural order of employee) then you can go for either Comparable or Comparator. Both are legal. If you would use Comparator then you have to write extra classes as comparator.

And if you have to sort employees on id and also on salary and Date of Joining, then use Comparable for id ad create comparators for salary and  Date of joining.

Suppose you are given list of objects of type Integer. Then which interface you will use? None, as Integer already implements Comparable. Just pass its array (or List) to Arrays.sort() (or Collections.sort()).

3) What is the difference between Comparable and Comparator?


Check here for this: Difference between Comparable and Comparator Interfaces.

 4) Which is preffered Comparable or Comparator?

Comparable has advantage that it avoids the creation of more number of classes and also elements implementing Comparable can be used directly in utility functions like  Arrays.sort()  and Collections.sort().

While Comparator is more flexible.It has advantage that it avoids the changing the class you are going to sort and more sorting criterias can be added later.

So in my view one should go for Comparable first for that sorting criteria which is not going to change in future and for additional criterias we can use Comparator in addition also.


5) Why do you need Comparable if  Comparator can also sort things?

Because Comparable :-

1) makes it easy to use the elements implementing it in some utility functions and classes like TreeSet and TreeMap.


2) Avoids creation of new classes.

I would like to know your comments and if you liked the article then please share it on social networking buttons.


Comparable and Comparator -Part 3



Using Arrays.sort() and Collections.sort() with Comparable

In EmployeeComparision class in part 2 you have compared two employees using 'if 'clause as:

if(emp1.compareTo(emp2) < 0)

This is good for comparing only two employees but in real situations there may be many employees and you may have an array or a list containing them. Then you can use sort() method of Arrays class as:

EmployeeComparision.java
import java.util.Arrays;

public class EmployeeComparision{
 
    public static void main(String args[]){
     
        Employee emp1 = new Employee();      
        emp1.setEmpId(3);
        emp1.setName("Mr. A");
        emp1.setCity("NY");
        emp1.setSalary(25000.0);
      
        Employee emp2 = new Employee();      
        emp2.setEmpId(2);
        emp2.setName("Mr. B");
        emp2.setCity("Los Angeles");
        emp2.setSalary(35000.0);
     
        Employee emp3 = new Employee();      
        emp3.setEmpId(1);
        emp3.setName("Mr. C");
        emp3.setCity("Chicago");
        emp3.setSalary(35000.0);
      
        Employee emp4 = new Employee();      
        emp4.setEmpId(4);
        emp4.setName("Mr. D");
        emp4.setCity("Los Angeles");
        emp4.setSalary(35000.0);
      
        Employee emp5 = new Employee();      
        emp5.setEmpId(5);
        emp5.setName("Mr. E");
        emp5.setCity("Boston");
        emp5.setSalary(35000.0);
      
        /* An array containing Employees */
        Employee [] empArray = new Employee[5];
        empArray[0]=emp1;
        empArray[1]=emp2;
        empArray[2]=emp3;
        empArray[3]=emp4;
        empArray[4]=emp5;
      
        System.out.println("Employees in acsending order(according to their ids):");
     
        Arrays.sort(empArray);

        for(int i=0;i<=4;i++){
        System.out.println(empArray[i].getName()+", ");
      
        }      
      
    }

}

Similarly you can use Collections.sort() in above code. Collections.sort() accepts List as argument instead of an array:


/* A List containing Employees */
  List<Employee> empList = new ArrayList<Employee>();
  empList.add(emp1);
  empList.add(emp2);
  empList.add(emp3);
  empList.add(emp4);
  empList.add(emp5);
  
 System.out.println("Employees in acsending order(according to their ids):");
     
 Collections.sort(empList);

 for(int i=0;i<empList.size();i++){
  System.out.println(empList.get(i).getName()+", ");
}


So up to now in part 1, part 2, part 3 and in part 4 you have been writing code to sort your Employee instances based on their ids. But suppose now you have a requirement of sorting employess in ascending order of their names also. What would you do? Would you change logic in compareTo() method for sorting employess according to their names? -- Nah!

And suppose sometimes later you again have a requirement of sorting your employees according to their salary. Would you again change compareTo() for this?  Again Nah!

What you need for this is Comparator interface.

Click on Next >> to read about Comparator.







I would like to know your comments and if you liked the article then please share it on social networking buttons.