In this article, we are going to learn deep copy ArrayList in Java.
Table of Contents
Shallow copy
and deep copy
.
When an object gets copied via reference not actual values then it is called Shallow copy
. In it, changes made to an object will also reflect to another object. It means if we change elements of one object then the other object will also be changed.
In deep copy
, the copied object is completely independent and changes made to it do not reflect to the original object.
Let’s understand with the examples.
Example of Deep Copy ArrayList
Here, we are copying one ArrayList elements to ther using addAll()
method and see changes made to second list does not modify original list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import java.util.ArrayList; public class Main { public static void main(String args[]) { ArrayList<String> list = new ArrayList<>(); list.add("India"); list.add("US"); list.add("China"); System.out.println(list); ArrayList<String> list2 = new ArrayList<>(); list2.addAll(list); System.out.println(list2); list2.set(1, "Russia"); System.out.println(list2); } } |
Output:
Note: This method will only work if ArrayList contains primitive data types or immutable collection. In case, ArrayList contains custom objects, then we need to explicitly clone the custom objects.
Deep Copy using Clone()
Method
We can also use clone()
method to create a copy of ArrayList but this method create swallow copy.
Let’s see with the help of example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
package org.arpit.java2blog.published; import java.util.Date; class Student implements Cloneable{ String name; String id; Date dateOfBirth; public Student(String name, String id,Date dateOfBirth) { this.name = name; this.id = id; this.dateOfBirth=dateOfBirth; } @Override public Student clone() { Student clonedStudent = null; try { clonedStudent = (Student) super.clone(); clonedStudent.setDateOfBirth((Date)this.dateOfBirth.clone()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clonedStudent; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Date getDateOfBirth() { return dateOfBirth; } public void setDateOfBirth(Date dateOfBirth) { this.dateOfBirth = dateOfBirth; } } |
Create main class named CloneArrayListMain.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import java.util.Date; public class CloneArrayListMain { public static void main(String[] args) { ArrayList<Student> studentList = new ArrayList<>(); studentList.add(new Student("Rohan","102",new Date(2002, 02, 12))); studentList.add(new Student("David","105",new Date(1999, 05, 30))); ArrayList<Student> clonedStudentList = (ArrayList<Student>) studentList.clone(); // Update cloned list clonedStudentList.get(0).setName("John"); System.out.println("-----------Original List-----------"); studentList.forEach(e->System.out.println(e.getName()+" "+e.getId())); System.out.println("-----------Copied List----------"); clonedStudentList.forEach(e->System.out.println(e.getName()+" "+e.getId())); } } |
Output
John 102
David 105
———–Copied List———-
John 102
David 105
As you can see, changes to clonedStudentList
also got reflected in studentList
.
To create a true deep copy of ArrayList, we should create a new ArrayList and copy all the cloned elements to new ArrayList one by one and we should also clone Student object properly.
To create deep copy of Student class, we can divide its class members to mutable and immutable types.
- Immutable fields(
String
data types): We can directly use immutable fields in cloned object. Immutable fields include wrapper classes,String
and primitive types. - Mutable fields(
Date
data type): We should create new object for the mutable attribute and then assign it to cloned object.
Here is the correct clone method for Student
class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@Override public Student clone() { Student clonedStudent = null; try { clonedStudent = (Student) super.clone(); clonedStudent.setDateOfBirth((Date)this.dateOfBirth.clone()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clonedStudent; } |
As you can see, we have used super.clone()
to clone the Student
object and then set dateOfBirth
explicitly to clonedStudent
as Date
is mutable field.
Here is code to create deep copy of ArrayList by copying cloned elements one by one to new ArrayList.
1 2 3 4 5 6 7 8 9 10 11 12 |
ArrayList<Student> studentList = new ArrayList<>(); studentList.add(new Student("Rohan","102",new Date(2002, 02, 12))); studentList.add(new Student("David","105",new Date(1999, 05, 30))); ArrayList<Student> clonedStudentList = new ArrayList<>(); for(Student st:studentList) { clonedStudentList.add(st.clone()); } |
Complete code to deep copy ArrayList in java
Here is complete java program to create deep copy of ArrayList in java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class CloneArrayListMain { public static void main(String[] args) { ArrayList<Student> studentList = new ArrayList<>(); studentList.add(new Student("Rohan","102",new Date(2002, 02, 12))); studentList.add(new Student("David","105",new Date(1999, 05, 30))); ArrayList<Student> clonedStudentList = new ArrayList<>(); for(Student st:studentList) { clonedStudentList.add(st.clone()); } // Update list clonedStudentList.get(0).setName("John"); System.out.println("-----------Original List-----------"); studentList.forEach(e->System.out.println(e.getName()+" "+e.getId())); System.out.println("-----------Copied List----------"); clonedStudentList.forEach(e->System.out.println(e.getName()+" "+e.getId())); } } |
As you can see, changes made to clonedStudentList
did not reflect in original ArrayList studentList
.
That’s all about how to deep copy ArrayList in java.