Monday, May 04, 2015

Deep Copy or Deep Cloning And Shallow Copy or Shallow Cloning

Cloning is very important aspect of OOPS in JAVA.

With the help of cloaning we can stop creating the huge number of object and can also create the object with specific value at specific time of execution.

All good thing comes with some problem same is the case with JAVA Clone.

Their are two type of clone in java

1- Shallow Clone
2- Deep Clone


1- Swallow Clone :- In this type of cloan we are copying the address of the class object inside other class. So when we create an clone object using super.clone() a new object is created but when the original object get change that changes is also reflected in cloned object. This is because when we do swallow clone we are copying the address of the previous object.

let me try to expain this is diagram some time single image is more than thousand word :)



Class 1
- int a;
- Class 2;


if I clone Class 1 object using super.clone() and create a new object lets say cloneObject. when ever  class2 object change the same thing is also reflected in clonedObject even though it is different.

2- Deep Clone:- In this type of cloan we are creating the new object instead of copying the address of the class object inside other class. So when we create an clone object using new operator in clone() method  a new object is created and this did not change even when the original object get change i.e. this change is not reflected in cloned object. This is because when we do deep clone we are not copying the address of the previous object but we are creating the object

let me try to expain this is diagram some time single image is more than thousand word :)



Class 1
- int a;
- Class 2;


if I clone Class 1 object using new operator in Clone() method and create a new object lets say cloneObject. when ever  class2 object change now the same thing is will not be  reflected in clonedObject even though it is different.

Now lets try to expain with Code.

class Standard {

  private String name;

  public String getName() {
    return name;
  }

  public void setName(String s) {
    name = s;
  }

  public Standard(String s) {
    name = s;
  }
}

class Child implements Cloneable {
  //Contained object
  private Standard stand;

  private String name;

  public Standard getstand() {
return stand;
  }

  public String getName() {
return name;
  }

  public void setName(String s) {
name = s;
  }

  public Child(String s, String sub) {
name = s;
stand = new Standard(sub);
  }

  public Object clone() {
//shallow copy
try {
 return super.clone();
} catch (CloneNotSupportedException e) {
 return null;
}
  }
}

public class CopyTest {

  public static void main(String[] args) {
//Original Object
 Child stud = new Child("one", "1st");

System.out.println("Original Object: " + stud.getName() + " - "
+ stud.getstand().getName());

//Clone Object
Child clonedStud = (Child) stud.clone();

System.out.println("Cloned Object: " + clonedStud.getName() + " - "
+ clonedStud.getstand().getName());

stud.setName("second");
stud.getstand().setName("2nd");

System.out.println("Original Object after it is updated: " 
+ stud.getName() + " - " + stud.getstand().getName());

System.out.println("Cloned Object after updating original object: "
+ clonedStud.getName() + " - " + clonedStud.getstand().getName());

  }
}

/*Original Object: one - 1st
Cloned Object: one - 1st
Original Object after it is updated: second - 2nd
Cloned Object after updating original object: one - 2nd
*/

Now lets see the same example using Deep cloaning. In deep cloaning event though our Standard object is changed then also their is no impact in Cloned object.

class Child implements Cloneable {
  //Contained object
  private Subject subj;

  private String name;

  public Subject getSubj() {
return subj;
  }

  public String getName() {
return name;
  }

  public void setName(String s) {
name = s;
  }

  public Child(String s, String sub) {
name = s;
subj = new Subject(sub);
  }

  public Object clone() {
//Deep copy
Child s = new Child(name, subj.getName());
return s;
  }
}


Original Object: one - 1st
Cloned Object: one - 1st
Original Object after it is updated: second - 2nd
Cloned Object after updating original object: one - 1st

What is the use of comparable and comparator interfaces in java.When should developer use the same.



What is the use of comparable and comparator interfaces in java.When should developer use the same.

Sorting is one of the main event which any developer need to face in his carrier. That sorting might be on int value or string value, in array, or Collections etc.

Java API gives us beautiful two interface comparable and comparator which assist doing the same.

Comparable interface contains method compareTo(Object  o) which is used to compare the same class Object.

Comparator interface contain method compare(Object  o1, Object  o2) which is used to compare two different object either of same class or of different class.

Lets apply force and try to understand use of this interface using simple java programe.

Lets say we had class Student having id and name as a field.

We got a requirement in which we need to sort this Student class object filled in collections  in both way by id and by name.

Lets  go first with sorting by default using id

public class Student implements Comparable {
    private int id = 0;
    private String firstName = null;
    private String lastName = null;


    public Student(int id, String fName, String lName) {
        this.id = id;
        this.firstName = fName;
        this.lastName = lName;
        
    }

    @Override
    public int compareTo(Student o) {
        return this.id - o.id;
    }

    @Override
    public String toString() {
        return "Student : " + id + " - " + firstName + " - " + lastName;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    
}


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

public class TestSorting {
    public static void main(String[] args) {
    Student e1 = new Student(1, "afirstname", "aLastName");
    Student e2 = new Student(2, "cfirstname", "cLastName");
        Student e3 = new Student(3, "bfirstname", "bLastName");
         
        List Students = new ArrayList();
        Students.add(e2);
        Students.add(e3);
        Students.add(e1);
         
        // UnSorted List
        System.out.println(Students);

        Collections.sort(Students);
        // Default Sorting by Student id
        System.out.println(Students);
    }
}


Out Put:-

[Student : 2 - cfirstname - cLastName, Student : 3 - bfirstname - bLastName, Student : 1 - afirstname - aLastName]
[Student : 1 - afirstname - aLastName, Student : 2 - cfirstname - cLastName, Student : 3 - bfirstname - bLastName]


Now lets check the condition when we need to sort the same student class by name i.e. firstName and lastName.

For this we need to use Comparator interface having compareTo(Object o1, Object o2).


Lets us create two class

import java.util.Comparator;

public class FirstNameSorter implements Comparator{

@Override
public int compare(Student o1, Student o2) {
return o1.getFirstName().compareTo(o2.getFirstName());
}
}


import java.util.Comparator;

public class LastNameSorter implements Comparator {

    @Override
    public int compare(Student o1, Student o2) {
        return o1.getLastName().compareTo(o2.getLastName());
    }

}

public class Student implements Comparable {
    private int id = 0;
    private String firstName = null;
    public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

private String lastName = null;
    

    public Student(int id, String fName, String lName) {
        this.id = id;
        this.firstName = fName;
        this.lastName = lName;
        
    }

    @Override
    public int compareTo(Student o) {
        return this.id - o.id;
    }

    @Override
    public String toString() {
        return "Student : " + id + " - " + firstName + " - " + lastName;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    
}

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

public class TestSorting {
public static void main(String[] args) {
    Student e1 = new Student(1, "afirstname", "aLastName");
    Student e2 = new Student(2, "cfirstname", "cLastName");
        Student e3 = new Student(3, "bfirstname", "bLastName");
         
        List Students = new ArrayList();
        Students.add(e2);
        Students.add(e3);
        Students.add(e1);

        // UnSorted List
        System.out.println(Students);

        Collections.sort(Students);
        // Default Sorting by Student id
        System.out.println(Students);

        Collections.sort(Students, new FirstNameSorter());
        // Sorted by firstName
        System.out.println(Students);

        Collections.sort(Students, new LastNameSorter());
        // Sorted by lastName
        System.out.println(Students);
         
    }
}




OUT PUT:- 
[Student : 2 - cfirstname - cLastName, Student : 3 - bfirstname - bLastName, Student : 1 - afirstname - aLastName]
[Student : 1 - afirstname - aLastName, Student : 2 - cfirstname - cLastName, Student : 3 - bfirstname - bLastName]
[Student : 1 - afirstname - aLastName, Student : 3 - bfirstname - bLastName, Student : 2 - cfirstname - cLastName]
[Student : 1 - afirstname - aLastName, Student : 3 - bfirstname - bLastName, Student : 2 - cfirstname - cLastName]