How to Deep Copy an Array in Java

Rupam Yadav Feb 12, 2024
  1. Understanding Deep Copy in Java
  2. Deep Copy Arrays in Java Using the System.arraycopy Method
  3. Deep Copy Arrays in Java Using the Arrays.copyOf Method
  4. Deep Copy Arrays in Java Using the clone Method
  5. Deep Copy Arrays in Java Using Java Streams
  6. Conclusion
How to Deep Copy an Array in Java

In Java, creating a deep copy of an array is essential when you want to duplicate its content without referencing the original array. This prevents unintended modifications to the original data and ensures that changes made to one array do not affect the other.

In this article, we’ll explore various techniques for achieving deep copies of arrays in Java and discuss the strengths and considerations associated with each method.

Understanding Deep Copy in Java

A deep copy involves creating a new array and copying the contents of the original array to the new one. Unlike a shallow copy, which merely references the same objects, a deep copy creates entirely new instances of the objects within the array.

This is crucial when dealing with complex data structures or objects with internal states, as it prevents unintended side effects.

Deep Copy Arrays in Java Using the System.arraycopy Method

The System.arraycopy method is a utility method provided by Java to efficiently copy elements from one array to another. It allows you to specify the source array, the starting position in the source array, the destination array, the starting position in the destination array, and the total number of elements to copy.

Its syntax is as follows:

System.arraycopy(srcArray, srcPos, destArray, destPos, length);

Where:

  • srcArray: The source array from which elements will be copied.
  • srcPos: The starting position in the source array.
  • destArray: The destination array where elements will be copied.
  • destPos: The starting position in the destination array.
  • length: The number of elements to be copied.

Let’s consider an example where we have an array arr1 containing integer elements. We want to create a deep copy into another array, arr2, using System.arraycopy.

Here’s the complete code:

import java.util.Arrays;

public class DeepCopyUsingSystemArrayCopy {
  public static void main(String[] args) {
    int[] arr1 = {10, 20, 30};
    int[] arr2 = new int[arr1.length];

    System.arraycopy(arr1, 0, arr2, 0, arr1.length);

    System.out.println("Original Array (arr1): " + Arrays.toString(arr1));
    System.out.println("Deep Copied Array (arr2): " + Arrays.toString(arr2));

    arr2[0] = 99;

    System.out.println("Modified Copied Array (arr2): " + Arrays.toString(arr2));
    System.out.println("Original Array (arr1) remains unchanged: " + Arrays.toString(arr1));
  }
}

In this example, we begin by defining a public class named DeepCopyUsingSystemArrayCopy. Inside the main method, which serves as the entry point of our program, we create an array named arr1 with elements 10, 20, and 30.

To perform a deep copy, we initialize a new array arr2 with the same length as arr1 using the statement int[] arr2 = new int[arr1.length];. This ensures that arr2 has enough space to accommodate the elements of arr1.

The System.arraycopy method is then utilized to perform the deep copy. It takes five arguments:

  • arr1: This is the source array.
  • 0: This is the starting position in the source array.
  • arr2: This is the destination array.
  • 0: This is the starting position in the destination array.
  • arr1.length: This is the number of elements to copy (the length of arr1).

After the deep copy, we use System.out.println to display the contents of both the original and copied arrays. We utilize Arrays.toString to convert the array elements into a human-readable string format for printing.

Following the initial display, we modify an element in the copied array arr2 by setting arr2[0] to 99. This modification showcases the independence of the two arrays; changes made to arr2 do not affect the original array arr1.

Code Output:

Original Array (arr1): [10, 20, 30]
Deep Copied Array (arr2): [10, 20, 30]
Modified Copied Array (arr2): [99, 20, 30]
Original Array (arr1) remains unchanged: [10, 20, 30]

As expected, the output confirms that the modification in arr2 doesn’t alter the contents of the original array arr1.

Deep Copy Arrays in Java Using the Arrays.copyOf Method

In addition to System.arraycopy, Java provides another convenient method for deep copying arrays - Arrays.copyOf. This method simplifies the process of creating a new array with copied elements from the original array.

Arrays.copyOf is part of the java.util package and is specifically designed for creating a new array with a specified length and copying elements from an existing array into it. This method is overloaded, providing variations for copying arrays of different types and accommodating situations where the new length may be different from the original array length.

The syntax is as follows:

int[] newArray = Arrays.copyOf(originalArray, length);

Where:

  • originalArray: The source array from which elements will be copied.
  • length: The desired length of the new array.

Let’s consider an example where we have an array arr1 containing integer elements. We want to create a deep copy into another array, arr2, using Arrays.copyOf.

Here’s the complete Java code:

import java.util.Arrays;

public class DeepCopyUsingArraysCopyOf {
  public static void main(String[] args) {
    int[] arr1 = {10, 20, 30};
    int[] arr2 = Arrays.copyOf(arr1, arr1.length);

    System.out.println("Original Array (arr1): " + Arrays.toString(arr1));
    System.out.println("Deep Copied Array (arr2): " + Arrays.toString(arr2));

    arr2[0] = 99;

    System.out.println("Modified Copied Array (arr2): " + Arrays.toString(arr2));
    System.out.println("Original Array (arr1) remains unchanged: " + Arrays.toString(arr1));
  }
}

In this example, we start by defining a public class named DeepCopyUsingArraysCopyOf. Inside the main method, we create an array named arr1 with elements 10, 20, and 30.

To perform a deep copy, we use the Arrays.copyOf method. This method takes the original array arr1 and its length as parameters, creating a new array arr2 with the same elements.

The deep copy ensures that modifications made to one array do not affect the other.

Following the deep copy operation, we employ System.out.println to display the contents of both the original and copied arrays. We use Arrays.toString to convert the array elements into a human-readable string format for printing.

After the initial display, we modify an element in the copied array arr2 by setting arr2[0] to 99. This modification demonstrates the independence of the two arrays; changes made to arr2 do not affect the original array arr1.

Code Output:

Original Array (arr1): [10, 20, 30]
Deep Copied Array (arr2): [10, 20, 30]
Modified Copied Array (arr2): [99, 20, 30]
Original Array (arr1) remains unchanged: [10, 20, 30]

As expected, the output confirms that the modification in arr2 doesn’t alter the contents of the original array arr1. This demonstration emphasizes the effectiveness of Arrays.copyOf in achieving a deep copy.

Deep Copy Arrays in Java Using the clone Method

Another method for achieving deep copies of arrays in Java, especially when dealing with arrays of objects, is through the use of the clone method. This method is particularly handy when you want to create a completely independent copy of an array.

The clone method is a member of the Object class, and it is used to create a new object that is an exact copy of the original object. In the context of arrays, we can leverage this method to create a deep copy.

The syntax for deep copying an array of objects using clone is as follows:

DataType[] newArray = originalArray.clone();

Here, originalArray is the array that you want to deep copy.

Let’s consider an example where we have an array arr1 containing objects of a custom class. We want to create a deep copy into another array, arr2, using the clone method.

Here’s the complete code:

import java.util.Arrays;

class CustomObject {
  int value;

  CustomObject(int value) {
    this.value = value;
  }
}

public class DeepCopyUsingClone {
  public static void main(String[] args) {
    CustomObject[] arr1 = {new CustomObject(10), new CustomObject(20), new CustomObject(30)};
    CustomObject[] arr2 = arr1.clone();

    System.out.println("Original Array (arr1): " + Arrays.toString(arr1));
    System.out.println("Deep Copied Array (arr2): " + Arrays.toString(arr2));

    arr2[0].value = 99;

    System.out.println("Modified Copied Array (arr2): " + Arrays.toString(arr2));
    System.out.println("Original Array (arr1) remains unchanged: " + Arrays.toString(arr1));
  }
}

In this example, we start by defining a custom class CustomObject with a single field value. Inside the main method of the DeepCopyUsingClone class, we create an array arr1 containing objects of this custom class.

To perform a deep copy, we use the clone method on the array arr1. This creates a new array, arr2, that is an independent copy of arr1.

It’s important to note that the elements within the array are still references to the same objects, so modifying the properties of these objects will affect both arrays.

After the deep copy, we employ System.out.println to display the contents of both the original and copied arrays. We use Arrays.toString to convert the array elements into a human-readable string format for printing.

Following the initial display, we modify the value field of an element in the copied array arr2. This modification showcases that, although the arrays themselves are independent, they still reference the same objects.

Therefore, changes made to the objects will be reflected in both arrays.

Code Output:

Original Array (arr1): [CustomObject@3fee733d, CustomObject@5acf9800, CustomObject@4617c264]
Deep Copied Array (arr2): [CustomObject@3fee733d, CustomObject@5acf9800, CustomObject@4617c264]
Modified Copied Array (arr2): [CustomObject@3fee733d, CustomObject@5acf9800, CustomObject@4617c264]
Original Array (arr1) remains unchanged: [CustomObject@3fee733d, CustomObject@5acf9800, CustomObject@4617c264]

As expected, the output confirms that modifying an object within arr2 also changes the corresponding object in the original array arr1. This example illustrates the behavior of the clone method in the context of deep copying arrays of objects.

Deep Copy Arrays in Java Using Java Streams

In Java, with the introduction of streams in Java 8, we have a concise and expressive way to perform operations on collections, including deep copying arrays.

To deep copy an array using Java Streams, we can utilize the Arrays.stream method to convert the array into a stream, followed by the toArray method to convert the stream back into an array. The syntax is as follows:

DataType[] newArray = Arrays.stream(originalArray).toArray(DataType[] ::new);

Here, originalArray is the array that you want to deep copy.

To use Java Streams for deep copying arrays, we need to consider whether the array elements are mutable or immutable.

For arrays of immutable objects, the process is straightforward. For mutable objects, we may need to provide a custom copying mechanism.

Let’s consider an example where we have an array arr1 containing integer elements. We want to create a deep copy into another array, arr2, using Java Streams.

Here’s the complete code:

import java.util.Arrays;

public class DeepCopyUsingStreams {
  public static void main(String[] args) {
    int[] arr1 = {10, 20, 30};
    int[] arr2 = Arrays.stream(arr1).toArray();

    System.out.println("Original Array (arr1): " + Arrays.toString(arr1));
    System.out.println("Deep Copied Array (arr2): " + Arrays.toString(arr2));

    arr2[0] = 99;

    System.out.println("Modified Copied Array (arr2): " + Arrays.toString(arr2));
    System.out.println("Original Array (arr1) remains unchanged: " + Arrays.toString(arr1));
  }
}

In this example, we start by defining a public class named DeepCopyUsingStreams. Inside the main method, we create an array arr1 containing integer elements.

To perform a deep copy using Java Streams, we use the Arrays.stream method on the original array arr1. This converts the array into an IntStream. We then use the toArray method without any arguments to convert the stream back into an array, effectively creating a deep copy arr2.

After the deep copy, we employ System.out.println to display the contents of both the original and copied arrays. We use Arrays.toString to convert the array elements into a human-readable string format for printing.

Following the initial display, we modify an element in the copied array arr2. This modification showcases the independence of the two arrays; changes made to arr2 do not affect the original array arr1.

Code Output:

Original Array (arr1): [10, 20, 30]
Deep Copied Array (arr2): [10, 20, 30]
Modified Copied Array (arr2): [99, 20, 30]
Original Array (arr1) remains unchanged: [10, 20, 30]

Conclusion

Deep copying arrays in Java is essential for maintaining data integrity and preventing unintended side effects in your programs. Each method—System.arraycopy, Arrays.copyOf, and Java Streams—comes with its advantages and use cases.

System.arraycopy provides granular control over copying elements and is suitable for both shallow and deep copies. Arrays.copyOf simplifies the process, especially when dealing with arrays of objects, offering a concise and readable solution.

Java Streams introduce a modern, functional programming paradigm, enhancing expressiveness and conciseness, which is especially beneficial when working with complex data structures.

The choice of method depends on the specific needs of your application, taking into consideration factors such as performance, readability, and the nature of the data being manipulated.

Author: Rupam Yadav
Rupam Yadav avatar Rupam Yadav avatar

Rupam Saini is an android developer, who also works sometimes as a web developer., He likes to read books and write about various things.

LinkedIn

Related Article - Java Array