How to Copy a Collection in Java? A Complete Guide with Examples
In Java, the process of copying collections is an essential operation that programmers often need to perform. Whether you are working with lists, sets, or maps, knowing how to make copies of collections—both shallow and deep—is crucial to avoid unintentional side effects in your program.
Introduction
Java provides a variety of collection classes, including ArrayList
, HashSet
, and HashMap
, to store and manage groups of objects. Sometimes, you may need to create a copy of a collection for further processing or manipulation, ensuring that changes to the copy do not affect the original collection.
This guide will explore how to copy collections in Java using various methods, including shallow copy and deep copy. We will also discuss the use of Java utility classes like Collections.copy()
and clone()
, as well as custom implementations for specific cases.
What is a Shallow Copy?
A shallow copy is a bit-wise copy of the collection. It copies the reference of the elements, rather than the elements themselves. This means that if the collection contains references to objects, the objects themselves are not copied. Instead, the references are copied, so changes to the objects in the copy will reflect in the original collection.
Shallow Copy with ArrayList
Let’s look at an example of making a shallow copy of an ArrayList
:
import java.util.ArrayList; public class ShallowCopyExample { public static void main(String[] args) { // Original ArrayList ArrayListoriginalList = new ArrayList<>(); originalList.add("Apple"); originalList.add("Banana"); originalList.add("Cherry"); // Shallow copy using clone() ArrayList shallowCopy = (ArrayList ) originalList.clone(); // Modify the shallow copy shallowCopy.set(0, "Orange"); // Print both lists System.out.println("Original List: " + originalList); System.out.println("Shallow Copy: " + shallowCopy); } }
In this example, we use the clone()
method to create a shallow copy of the original list. When we modify the shallow copy, the original list is not affected, as strings are immutable in Java. However, if we were to copy a collection of objects, the objects themselves would still be shared between the original and copied collections.
What is a Deep Copy?
A deep copy involves creating a completely independent copy of the collection, as well as making copies of all the objects contained in the collection. This ensures that changes made to the objects in the copied collection do not affect the objects in the original collection.
Deep Copy with ArrayList
To perform a deep copy, you need to manually copy the elements if they are complex objects. Below is an example:
import java.util.ArrayList; class Item { String name; public Item(String name) { this.name = name; } @Override public String toString() { return name; } public Item deepCopy() { return new Item(this.name); } } public class DeepCopyExample { public static void main(String[] args) { // Original ArrayList of custom objects ArrayList- originalList = new ArrayList<>(); originalList.add(new Item("Apple")); originalList.add(new Item("Banana")); originalList.add(new Item("Cherry")); // Deep copy using custom method ArrayList
- deepCopy = new ArrayList<>(); for (Item item : originalList) { deepCopy.add(item.deepCopy()); } // Modify the deep copy deepCopy.get(0).name = "Orange"; // Print both lists System.out.println("Original List: " + originalList); System.out.println("Deep Copy: " + deepCopy); } }
In this example, we perform a deep copy of an ArrayList
containing custom objects. The deepCopy()
method creates a new instance of the Item
object, ensuring that the original collection and the copied collection do not share the same object references.
Copying Collections Using Java Utility Methods
Java provides some built-in methods to facilitate copying collections. The Collections.copy()
method is one such utility. It is designed to copy elements from one list to another. Note that the destination list must be large enough to accommodate all elements from the source list. It is also worth noting that Collections.copy()
performs a shallow copy.
Example: Using Collections.copy()
import java.util.ArrayList; import java.util.Collections; public class CollectionsCopyExample { public static void main(String[] args) { // Original ArrayList ArrayListoriginalList = new ArrayList<>(); originalList.add("Apple"); originalList.add("Banana"); originalList.add("Cherry"); // Create a destination list with the same size ArrayList copyList = new ArrayList<>(originalList.size()); // Copy using Collections.copy() Collections.copy(copyList, originalList); // Modify the copy copyList.set(0, "Orange"); // Print both lists System.out.println("Original List: " + originalList); System.out.println("Copy List: " + copyList); } }
In the above code, we use the Collections.copy()
method to copy elements from the originalList
into the copyList
. The destination list is created with the same size as the source list. After the copy, we modify the copied list, and it does not affect the original list.
Copying Collections Using the Clone Method
The clone()
method is another built-in Java method that can be used to copy collections. This method works only for classes that implement the Cloneable
interface. It creates a shallow copy of the collection.
Example: Using clone() to Copy an ArrayList
import java.util.ArrayList; public class CloneMethodExample { public static void main(String[] args) { // Original ArrayList ArrayListoriginalList = new ArrayList<>(); originalList.add("Apple"); originalList.add("Banana"); originalList.add("Cherry"); // Clone the list ArrayList clonedList = (ArrayList ) originalList.clone(); // Modify the cloned list clonedList.set(0, "Orange"); // Print both lists System.out.println("Original List: " + originalList); System.out.println("Cloned List: " + clonedList); } }
In this example, we use the clone()
method to create a shallow copy of the originalList
. We can modify the cloned list without affecting the original one, but remember, this is a shallow copy. If the list contained complex objects, the references to those objects would still be shared.
Conclusion
Copying collections in Java is a critical operation that ensures you maintain the integrity of your data structures when you need to work with duplicates. Depending on your needs, you can perform a shallow copy using methods like clone()
or Collections.copy()
, or create a deep copy if you need completely independent collections, such as by using custom copy methods for complex objects.
By understanding these different techniques, you can effectively handle collections in your Java programs and avoid unintended side effects caused by shared references.