- How to Clone a Collection in Java? Deep copy of ArrayList and HashSet Example
- Deep Cloning of Collection in Java
- How to Deep Copy Arraylist in Java
- Example of Deep Copy ArrayList
- Deep Copy using Clone() Method
- Complete code to deep copy ArrayList in java
- Was this post helpful?
- You may also like:
- Update Value of Key in HashMap in Java
- Create Array of Linked Lists in Java
- Return ArrayList in Java
- Create List with One Element in Java
- How to Add Multiple Values for Single Key In HashMap in Java
- [Fixed] java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList
- Create ArrayList of Objects in Java
- How to remove element from Arraylist in java while iterating
- Print HashMap in Java
- Print LinkedList in java
- Share this
- Related Posts
- Author
- Related Posts
- Update Value of Key in HashMap in Java
- Create Array of Linked Lists in Java
- Return ArrayList in Java
- Create List with One Element in Java
- How to Add Multiple Values for Single Key In HashMap in Java
- [Fixed] java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList
How to Clone a Collection in Java? Deep copy of ArrayList and HashSet Example
Programmers often mistook copy constructors provided by various collection classes, as a means to clone Collection like List , Set , ArrayList , HashSet, or any other implementation. What is worth remembering is that the copy constructor of Collection in Java only provides a shallow copy and not a deep copy, which means objects stored in both original Lists and cloned List will be the same and point to the same memory location in the Java heap. One thing, which adds to this misconception is a shallow copy of Collections with Immutable Objects. Since Immutable objects can’t be changed, It’s Ok even if two collections are pointing to the same object. This is exactly the case of String contained in the pool, update on one will not affect the other.
The problem arises when we use the Copy constructor of ArrayList to create a clone of List of Employees, where Employee is not Immutable. In this case, if the original collection modifies an employee, that change will also reflect into the cloned collection.
Similarly, if an employee is modified in the cloned collection, it will also appear as modified in the original collection. This is not desirable, in almost all cases, the clone should be independent of the original object. A solution to avoid this problem is deep cloning of collection, which means recursively cloning objects until you reached primitive or Immutable.
In this article, we will take a look at one approach of deep copying Collection classes like ArrayList or HashSet in Java. By the way, If you know the difference between shallow copy and deep copy, it would be very easy to understand how deep cloning of collection works.
And, If you are new to the Java world then I also recommend you go through The Complete Java MasterClass on Udemy to learn Java in a better and more structured way. This is one of the best and up-to-date courses to learn Java online.
Deep Cloning of Collection in Java
In the following example, we have a Collection of Employee , a mutable object, with a name and designation field. They are stored inside HashSet . We create another copy of this collection using the addAll() method of java.util.Collection interface. After that, we modified the designation of each Employee object stored in the original Collection.
Ideally, this change should not affect original Collection, because the clone and original object should be independent of each other, but it does. The solution to fix this problem is deep cloning of elements stored in the Collection class.
import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Java program to demonstrate copy constructor of Collection provides shallow * copy and techniques to deep clone Collection by iterating over them. * @author http://javarevisited.blogspot.com */ public class CollectionCloningTest < private static final Logger logger = LoggerFactory.getLogger(CollectionCloningclass); public static void main(String args[]) < // deep cloning Collection in Java Collectionorg = new HashSet<> (); org.add(new Employee("Joe", "Manager")); org.add(new Employee("Tim", "Developer")); org.add(new Employee("Frank", "Developer")); // creating copy of Collection using copy constructor Collection copy = new HashSet<> (org); logger.debug("Original Collection <>", org); logger.debug("Copy of Collection <>", copy ); Iterator itr = org.iterator(); while(itr.hasNext())< itr.next().setDesignation("staff"); > logger.debug("Original Collection after modification <>", org); logger.debug("Copy of Collection without modification <>", copy ); // deep Cloning List in Java > > class Employee < private String name; private String designation; public Employee(String name, String designation) < this.name = name; this.designation = designation; > public String getDesignation() < return designation; > public void setDesignation(String designation) < this.designation = designation; > public String getName() < return name; > public void setName(String name) < this.name = name; > @Override public String toString() < return String.format("%s: %s", name, designation ); > > Output : - Original Collection [Joe: Manager, Frank: Developer, Tim: Developer] - Copy of Collection [Joe: Manager, Frank: Developer, Tim: Developer] - Original Collection after modification [Joe: staff, Frank: staff, Tim: staff] - Copy of Collection without modification [Joe: staff, Frank: staff, Tim: staff]
You can see clearly that modifying the Employee object in the original Collection (changed the designation to «staff» ) is also reflecting in the cloned collection because the clone is a shallow copy and points to the same Employee object in the heap.
In order to fix this, we need to deep clone the Employee object by iterating over Collection, and before that, we need to override the clone method for the Employee object.
1) Let Employee implements Cloneable interface
2) Add following clone() method into Employee class
@Override protected Employee clone() < Employee clone = null; try< clone = (Employee) super.clone(); >catch(CloneNotSupportedException e)< throw new RuntimeException(e); // won't happen > return clone; >
3) Instead of using Copy constructor use following code, to deep copy Collection in Java
CollectionEmployee> copy = new HashSetEmployee>(org.size()); IteratorEmployee> iterator = org.iterator(); while(iterator.hasNext())
4) Running same code for modifying collection, will not result in different output:
— Original Collection after modification [Joe: staff, Tim: staff, Frank: staff]
— Copy of Collection without modification [Frank: Developer, Joe: Manager, Tim: Developer]
You can see that both clone and Collection are independent of each other and they are pointing to different objects.
That’s all on How to clone Collection in Java. Now we know that copy constructor or various collection classes like addAll() method of List or Set, only creates a shallow copy of Collection and both original and cloned Collection points to the same objects. To avoid this, we can deep copy collection, iterating over them and cloning each element. Though this requires that any object stored in Collection, must support deep cloning operation.
How to Deep Copy Arraylist in Java
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.
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.
Create main class named CloneArrayListMain.java
clonedStudentList . forEach ( e — > System . out . println ( e . getName ( ) + » » + e . getId ( ) ) ) ;
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.
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.
Complete code to deep copy ArrayList in java
Here is complete java program to create deep copy of ArrayList in java.
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.
Was this post helpful?
You may also like:
Update Value of Key in HashMap in Java
Create Array of Linked Lists in Java
Return ArrayList in Java
Create List with One Element in Java
How to Add Multiple Values for Single Key In HashMap in Java
[Fixed] java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList
Create ArrayList of Objects in Java
How to remove element from Arraylist in java while iterating
Print HashMap in Java
Print LinkedList in java
Share this
Related Posts
Author
Related Posts
Update Value of Key in HashMap in Java
Table of ContentsUsing the put() Method of HashMap Collection in JavaUsing the compute() Method of HashMap Collection in JavaUsing the merge() Method of the HashMap Collection in JavaUsing the computeIfPresent() Method of The HashMap Collection in JavaUsing the replace() Method of The HashMap Collection in JavaUsing the TObjectIntHashMap Class of Gnu.Trove Package in JavaUsing the […]
Create Array of Linked Lists in Java
Table of ContentsIntroductionLinked List in JavaApplication of Array of Linked ListsCreate Array of Linked Lists in JavaUsing Object[] array of Linked Lists in JavaUsing the Linked List array in JavaUsing the ArrayList of Linked Lists in JavaUsing the Apache Commons Collections Package Introduction In this article, we will look at how to Create an Array […]
Return ArrayList in Java
Table of ContentsReturn ArrayList in Java From a Static MethodReturn ArrayList in Java From a Non-static MethodConclusion This article discusses cases of returning an ArrayList in Java from a method. An ArrayList in Java is a collection of elements of the same data type under a single variable name. In different cases, you can return […]
Create List with One Element in Java
Table of ContentsUsing Collections.singletonList()Using Array.asList() method [ Immuatable list]Using new ArrayList with Array.asList() method [ Mutable list] In this post, we will see how to create List with One Element in java.. Using Collections.singletonList() This is best way to create List with single element if you need an immutable List. [crayon-64c259ba61332050881696/] Output [crayon-64c259ba61337034637233/] If you […]
How to Add Multiple Values for Single Key In HashMap in Java
Table of ContentsHashMapCan HashMap Store Multiple Values AutomaticallyWays to Add Multiple Values for Single Key In HashMap in JavaUsing the Standard LibraryUsing Apache Commons LibraryUsing Google Guava LibraryUsing TreeSet as ValuesUsing a Wrapper ClassUsing Java TuplesUsing compute() Function in JDK 8Conclusion This article discusses the HashMap in Java and how to add multiple values for […]
[Fixed] java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList
Table of ContentsReason for java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayListFixes for java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayListUse ArrayList’s constructorAssign Arrays.asList() to List reference rather than ArrayList In this post, we will see how to fix java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList. ClassCastException is runtime exception which indicate that code has tried to […]