ArrayList clone() method is used to create a shallow copy of the list. In the new list, only object references are copied.
If we change the object state inside the first ArrayList
, then the changed object state will be reflected in the cloned ArrayList
as well.
1. ArrayList clone() API
clone()
method create a new ArrayList
and then copies the backing array to cloned array.
public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(e); } }
- Method parameter – none.
- Method returns – cloned arraylist.
- Method throws – no exception.
2. Creating Shallow Copy
Java program to create a shallow copy of an arraylist using clone()
method.
import java.util.ArrayList; public class ArrayListExample { @SuppressWarnings("unchecked") public static void main(String[] args) { ArrayList<String> arrayListObject = new ArrayList<>(); arrayListObject.add("A"); arrayListObject.add("B"); arrayListObject.add("C"); arrayListObject.add("D"); System.out.println(arrayListObject); ArrayList<String> arrayListClone = (ArrayList<String>) arrayListObject.clone(); System.out.println(arrayListClone); } }
Program output.
[A, B, C, D] [A, B, C, D]
3. Creating Deep Copy
Creating a deep copy of a list is not straightforward. Java does not support deep copying by default. So we have to manually modify the code to enable the deep copying of classes and collections.
Read More : A guide to object cloning in Java
3.1. Deep copy of Java class
In Java, to support deep copy, we must override the clone()
of model classes. In clone()
method, we must ensure that when somebody invokes object.clone()
method then it must return a deep copy of that model class (e.g. Employee
class).
To create a deep copy of the class, divide all the class members into two categories of mutable and immutable types.
- All immutable field members can be used as it is. They don’t require any special treatment. e.g. primitive classes, wrapper classes and
String
class. - For all immutable field members, we must create a new object of member and assign it’s value to cloned object.
The idea is to return an immutable copy of the class from clone()
method.
package com.howtodoinjava.example; import java.util.Date; public class Employee implements Cloneable { private Long id; private String name; private Date dob; //Mutable field public Employee(Long id, String name, Date dob) { super(); this.id = id; this.name = name; this.dob = dob; } //Getters and setters @Override protected Object clone() throws CloneNotSupportedException { Employee clone = null; try { clone = (Employee) super.clone(); //Copy new date object to cloned method clone.setDob((Date) this.getDob().clone()); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } return clone; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", dob=" + dob + "]"; } }
3.2. Deep copy of Java Collections
Creating a deep copy of a collection is rather easy. We need to create a new instance of collection and copy all elements from given collection to cloned collection – one by one. Note that we will copy the element’s clone in cloned collection.
ArrayList<Employee> employeeList = new ArrayList<>(); ArrayList<Employee> employeeListClone = new ArrayList<>(); Iterator<Employee> iterator = employeeList.iterator(); while(iterator.hasNext()) { //Add the object clones employeeListClone.add((Employee) iterator.next().clone()); }
3.3. ArrayList deep copy example
Java program to create a deep copy of an arraylist.
package com.howtodoinjava.example; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; public class ArrayListExample { @SuppressWarnings("deprecation") public static void main(String[] args) throws CloneNotSupportedException { ArrayList<Employee> employeeList = new ArrayList<>(); employeeList.add(new Employee(1l, "adam", new Date(1982, 02, 12))); System.out.println(employeeList); ArrayList<Employee> employeeListClone = new ArrayList<>(); Iterator<Employee> iterator = employeeList.iterator(); while(iterator.hasNext()){ employeeListClone.add((Employee) iterator.next().clone()); } employeeListClone.get(0).setId(2l); employeeListClone.get(0).setName("brian"); employeeListClone.get(0).getDob().setDate(13);; System.out.println(employeeList); System.out.println(employeeListClone); } }
Program output. Notice that even after changing the values of Employee
object in employeeListClone
, original employee list employeeList
is not changed.
[Employee [id=1, name=adam, dob=Sun Mar 12 00:00:00 IST 3882]] [Employee [id=1, name=adam, dob=Sun Mar 12 00:00:00 IST 3882]] [Employee [id=2, name=brian, dob=Mon Mar 13 00:00:00 IST 3882]]
Happy Learning !!
Read More:
A Guide to Java ArrayList
ArrayList Java Docs
I should say in the following line, you not need to have .clone() at the end.
while(iterator.hasNext()){
employeeListClone.add((Employee) iterator.next().clone());
}
Hi Lokesh,
Running the Employee class in section 3.1 for deep clone, the section in which you are making a clone of dob (this.dob.clone()) will the clone method be visible .