What is Arrays.copyOf() method in Java?
Java class java.util.Arrays provides a method called Arrays.copyOf() that returns a copy of an array passed as a parameter to this function, followed by specifying its size. Here’s the method header for quick understanding.
Arrays.copyOf(int[] templateArray, int length);
Note that the second parameter “length” is the size of the copy array you want to create. So here we can have 3 cases.- The lengths of both template & copy arrays are the same.
- The length of the copy array is greater than the length of the template array.
- The length of the copy array is lesser than the length of the template array.

Coding Example
import java.util.Arrays;
public class ArraysCopyOfMethod {
public static void main(String[] args) {
// Initialize your templateArray which you want a copy of
int[] templateArray = new int[] {1, 2, 3, 4, 5, 6};
System.out.println("Template Array: " + Arrays.toString(templateArray));
// Create a "copy" of template array using
// Arrays.copyOf(int[] array, int arrayLength) method
// CASE 1: Sizes of both template & copy arrays are same
int[] copyArray1 = Arrays.copyOf(templateArray, templateArray.length);
System.out.println("Copy Array 1: " + Arrays.toString(copyArray1));
// CASE 2: Size of copy array > Size of template array
// extra space in copy array is filled with zeros
int[] copyArray2 = Arrays.copyOf(templateArray, 10);
System.out.println("Copy Array 2: " + Arrays.toString(copyArray2));
// CASE 3: Size of copy array < Size of template array
// copy array is only filled with only elements in overlapping size
int[] copyArray3 = Arrays.copyOf(templateArray, 3);
System.out.println("Copy Array 3: " + Arrays.toString(copyArray3));
}
}
Output
Copying 2D Arrays Using Loops
Copying 2D arrays manually using loops ensures greater control and enables deep copying, which creates new instances of nested arrays.
Example: Manual Copy of 2D Arrays
import java.util.Arrays;
public class ManualCopyExample {
public static void main(String[] args) {
int[][] original = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int[][] copy = new int[original.length][];
for (int i = 0; i < original.length; i++) {
copy[i] = Arrays.copyOf(original[i], original[i].length);
}
System.out.println("Original: " + Arrays.deepToString(original));
System.out.println("Copy: " + Arrays.deepToString(copy));
}
}
Output:
Original: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] Copy: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Challenges and Pitfalls: Shallow vs. Deep Copying
When copying arrays, understanding the distinction between shallow and deep copying is crucial:
- Shallow Copy: Copies only the references of nested arrays, not the actual elements. Modifying one array affects the other.
- Deep Copy: Creates new instances of nested arrays, ensuring changes to one array do not affect the other.
Using Arrays.copyOf()
for 2D arrays performs a shallow copy, which may lead to unintended consequences.
Using Built-In Methods for Copying 2D Arrays
Shallow Copy with Arrays.copyOf()
int[][] shallowCopy = Arrays.copyOf(original, original.length);
While this copies the outer array, the nested arrays remain shared, leading to potential issues if modified.
Deep Copy with Loops
The manual method described earlier ensures a deep copy, preventing unintended modifications.
Using External Libraries for Array Copying
Apache Commons: SerializationUtils.clone()
The Apache Commons library offers a straightforward way to deep copy arrays using serialization:
import org.apache.commons.lang3.SerializationUtils;
int[][] deepCopy = SerializationUtils.clone(original);
This method works for arrays of objects that implement Serializable
.
Apache Commons: ArrayUtils
The ArrayUtils
class provides various utilities for array manipulation, including deep copying.
import org.apache.commons.lang3.ArrayUtils;
int[][] deepCopy = ArrayUtils.clone(original);
Importance of Deep Copying with Non-Primitive Types
When working with arrays of non-primitive types, shallow copying only duplicates references. This can lead to shared state issues where modifying one element affects others.
Example:
class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Point[][] points = {
{new Point(1, 2), new Point(3, 4)},
{new Point(5, 6), new Point(7, 8)}
};
// Deep copying with loops or serialization ensures independence of Point objects.
Using Loops for Manual Array Copying
While Arrays.copyOf()
simplifies array copying, using loops offers greater control and flexibility. This method allows developers to customize the copying process, such as skipping certain elements or applying transformations during the copy.
Example: Copying a 1D Array with Loops
public class ManualCopyExample {
public static void main(String[] args) {
int[] original = {1, 2, 3, 4, 5};
int[] copy = new int[original.length];
for (int i = 0; i < original.length; i++) {
copy[i] = original[i];
}
System.out.println("Original: " + java.util.Arrays.toString(original));
System.out.println("Copy: " + java.util.Arrays.toString(copy));
}
}
Output:
Original: [1, 2, 3, 4, 5] Copy: [1, 2, 3, 4, 5]
Example: Copying a 2D Array with Loops
For multidimensional arrays, nested loops are used to copy each nested array:
public class ManualCopy2DExample {
public static void main(String[] args) {
int[][] original = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int[][] copy = new int[original.length][];
for (int i = 0; i < original.length; i++) {
copy[i] = new int[original[i].length];
for (int j = 0; j < original[i].length; j++) {
copy[i][j] = original[i][j];
}
}
System.out.println("Original: " + java.util.Arrays.deepToString(original));
System.out.println("Copy: " + java.util.Arrays.deepToString(copy));
}
}
Output:
Original: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] Copy: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Performance Considerations: Loops vs. Built-in Methods
When deciding between loops and built-in methods for array copying, consider the following factors:
- Small Arrays: Loops may be faster for small arrays due to reduced overhead compared to built-in methods like
Arrays.copyOf()
. - Large Arrays: Built-in methods are optimized and can leverage low-level system optimizations, making them faster for large arrays.
- Customization: Loops offer greater flexibility for custom copying requirements, such as filtering or transforming elements during the copy process.
Benchmark Example
import java.util.Arrays;
public class PerformanceComparison {
public static void main(String[] args) {
int[] original = new int[100000];
Arrays.fill(original, 42);
// Measure time for manual copy
long start = System.nanoTime();
int[] manualCopy = new int[original.length];
for (int i = 0; i < original.length; i++) {
manualCopy[i] = original[i];
}
long end = System.nanoTime();
System.out.println("Manual copy time: " + (end - start) + " ns");
// Measure time for Arrays.copyOf()
start = System.nanoTime();
int[] builtInCopy = Arrays.copyOf(original, original.length);
end = System.nanoTime();
System.out.println("Built-in copy time: " + (end - start) + " ns");
}
}
Understanding System.arraycopy
The System.arraycopy
method is a low-level array copying utility provided by Java. It offers efficient copying by utilizing native system calls, making it one of the fastest methods available.
Method Signature:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
Parameters:
src
: The source array from which elements are copied.srcPos
: The starting position in the source array.dest
: The destination array to which elements are copied.destPos
: The starting position in the destination array.length
: The number of elements to copy.
Example: Basic Array Copying
public class BasicArrayCopy {
public static void main(String[] args) {
int[] source = {1, 2, 3, 4, 5};
int[] destination = new int[5];
System.arraycopy(source, 0, destination, 0, source.length);
System.out.println("Source: " + java.util.Arrays.toString(source));
System.out.println("Destination: " + java.util.Arrays.toString(destination));
}
}
Output:
Source: [1, 2, 3, 4, 5] Destination: [1, 2, 3, 4, 5]
Flexibility and Efficiency of System.arraycopy
System.arraycopy
is preferred over other methods for its:
- Speed: Leveraging native system calls makes it faster than manual copying or
Arrays.copyOf()
. - Flexibility: Allows partial copying and precise control over the source and destination indices.
- Versatility: Can handle multi-dimensional arrays and custom copying scenarios efficiently.
Example: Partial Array Copying
public class PartialArrayCopy {
public static void main(String[] args) {
int[] source = {10, 20, 30, 40, 50};
int[] destination = new int[3];
System.arraycopy(source, 1, destination, 0, 3);
System.out.println("Source: " + java.util.Arrays.toString(source));
System.out.println("Destination: " + java.util.Arrays.toString(destination));
}
}
Output:
Source: [10, 20, 30, 40, 50] Destination: [20, 30, 40]
Example: Copying Between Different Array Segments
public class CopySegments {
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5, 6};
// Shift elements within the same array
System.arraycopy(array, 2, array, 1, 3);
System.out.println("Modified Array: " + java.util.Arrays.toString(array));
}
}
Output:
Modified Array: [1, 3, 4, 5, 5, 6]
Limitations and Precautions
- Type Matching: The source and destination arrays must be compatible in type; otherwise, an
ArrayStoreException
will be thrown. - Index Validation: Ensure valid indices to avoid
IndexOutOfBoundsException
. - Non-Primitive Arrays: For object arrays, shallow copies are performed. Use deep copying for nested objects.
GO TO FULL VERSION