How to Copy a Collection in Java?

How to Copy a Collection in Java? A Complete Guide with Examples

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
        ArrayList originalList = 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
        ArrayList originalList = 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
        ArrayList originalList = 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.

Please follow and like us:

Leave a Comment