Core Java

Java Copy Array Example

Photo of Mary ZhengMary ZhengApril 2nd, 2019Last Updated: July 6th, 2022
1 160 15 minutes read

1. Introduction

Java array is an object which represents a data structure that contains elements of a similar data type. Array in java is index-based; the first element of the array is stored at the 0 index. Java has provided several ways to copy array over time:

  • System.arraycopy – provided since version 1.0. It copies an array from a source array to a destination array. It starts the copy from the source position to the target position with the specified length.
  • Object.clone() – provided since version 1.0. It creates and returns a copy of the object. If the object is an array, then the array is cloned into a new array with the same content.
  • Arrays.copyOf– provided since version 1.6. It copies the specified array, truncating or padding with false (if necessary) so the copy has the specified length.
  • Arrays.copyOfRange – provided since version 1.6. It copies the specified range of the specified array into a new.
  • Stream.toArray – provides since version 1.8. It returns an array containing the elements of this stream. It is adeep copy as the copied array has a different object reference from the source array’s element object.

You can watch the following video and learn how to use arrays in Java:

Java Array Example How to use Arrays in Java – Video

Here are the methods’ signatures:

ClassMethodDefinition
ObjectObject clone () throws CloneNotSupportedException
Systemstatic void arraycopy (
Object src, int srcPos, Object dest, int destPos, int length)
Arraysstatic boolean[] copyOf (T[] src, int newLength)
static T[] copyOfRange (T[] src, int from, int to)
StreamObject[] toArray ()

Parameters Definition

  • src – the source array.
  • srcPos – starting position in the source array.
  • dest – the destination array.
  • destPos – starting position in the destination data.
  • length – the number of array elements.
  • newLength – the length of the copy to be returned.
  • from – the initial index of the range to be copied, inclusive.
  • to – the final index of the range to be copied, exclusive.

In this example, I will demonstrate these copy methods with the following items:

  • Copy anInteger,String, andObject array and compare the execution time and memory used.
  • Copy a two-dimensional (2D)Integer array and compare the execution time and memory used.
  • Copy anInteger andString array and compare the performance benchmark.

2. Technologies used

The example code in this article was built and run using:

  • Java 11
  • Maven 3.3.9
  • Eclipse Oxygen
  • JUnit 4.12
  • JMH 1.21
copy array java
copy array java

3. Maven Project

3.1 Dependency

Add Junit and JMH to the pom.xml.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.jcg.zheng</groupId><artifactId>copyarray-benchmark</artifactId><version>0.0.1-SNAPSHOT</version><properties><maven.compiler.target>11</maven.compiler.target><maven.compiler.source>11</maven.compiler.source></properties><dependencies><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-core</artifactId><version>1.21</version></dependency><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-generator-annprocess</artifactId><version>1.21</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies><build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><executions><execution><id>run-benchmarks</id><phase>integration-test</phase><goals><goal>exec</goal></goals><configuration><classpathScope>test</classpathScope><executable>java</executable><arguments><argument>-classpath</argument><classpath /><argument>org.openjdk.jmh.Main</argument><argument>.*</argument></arguments></configuration></execution></executions></plugin></plugins></build></project>

3.2 DemoObject

In this step, I will create aDemoObject class which has data members, getters, setters, and constructors.

DemoObject.java

package org.jcg.zheng;public class DemoObject {    private char charValue;    private String name;    private int number;    public DemoObject(final char charValue, final int number, final String name) {        super();        this.charValue = charValue;        this.name = name;        this.number = number;    }    public DemoObject(DemoObject dObj) {        if (dObj != null) {            this.name = dObj.getName();            this.charValue = dObj.getCharValue();            this.number = dObj.getNumber();        }    }    public char getCharValue() {        return charValue;    }    public String getName() {        return name;    }    public int getNumber() {        return number;    }    @Override    public String toString() {        return "DataObject [number=" + number + ", charValue=" + charValue + ", name=" + name + "]";    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + charValue;        result = prime * result + ((name == null) ? 0 : name.hashCode());        result = prime * result + number;        return result;    }    @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        DemoObject other = (DemoObject) obj;        if (charValue != other.charValue)            return false;        if (name == null) {            if (other.name != null)                return false;        } else if (!name.equals(other.name))            return false;        if (number != other.number)            return false;        return true;    }    public void setCharValue(char charValue) {        this.charValue = charValue;    }    public void setName(String name) {        this.name = name;    }    public void setNumber(int number) {        this.number = number;    }}

3.3 Copy Int Array Benchmark

JMH is a Java harness for building, running, and analyzing nano/micro/milli/macro benchmarks written in Java and other languages targeting the JVM.

In this step, I will create aCopyIntArrayBenchmark class which utilizes the JMH to show the performance benchmark when copying an integer array viaSystem.arraycopy,Arrays.copyOf,Arrays.copyOfRange,Stream.toArray, andObject.clone.

Please note thatEmptyArray is created as the comparing base and all the copying methods use the same source array data.

CopyIntArrayBenchmark.java

package org.jcg.zheng;import java.util.Arrays;import java.util.concurrent.TimeUnit;import org.openjdk.jmh.annotations.Benchmark;import org.openjdk.jmh.annotations.BenchmarkMode;import org.openjdk.jmh.annotations.Fork;import org.openjdk.jmh.annotations.Mode;import org.openjdk.jmh.annotations.OutputTimeUnit;import org.openjdk.jmh.annotations.Scope;import org.openjdk.jmh.annotations.State;import org.openjdk.jmh.annotations.Warmup;import org.openjdk.jmh.runner.Runner;import org.openjdk.jmh.runner.RunnerException;import org.openjdk.jmh.runner.options.Options;import org.openjdk.jmh.runner.options.OptionsBuilder;@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)@State(Scope.Benchmark)@Fork(value = 1)@Warmup(iterations = 2)public class CopyIntArrayBenchmark { private int[] sourceIntegerArray = { 1, 2, 3, 4, 5 }; @Benchmark public int[] Arrays_int_copyOfRange() { return Arrays.copyOfRange(sourceIntegerArray, 0, sourceIntegerArray.length); } @Benchmark public int[] Arrays_Stream_Int_toArray() { return Arrays.stream(sourceIntegerArray).toArray(); } @Benchmark public int[] clone_IntArray() { return sourceIntegerArray.clone(); } @Benchmark public int[] System_arraycopy() { int[] destination = new int[3]; System.arraycopy(sourceIntegerArray, 0, destination, 0, 3); return destination; } @Benchmark public int[] EmptyArray() { return new int[0]; } public static void main(String[] args) { Options opt = new OptionsBuilder().include(CopyIntArrayBenchmark.class.getSimpleName()).build(); try { new Runner(opt).run(); } catch (RunnerException e) { e.printStackTrace(); } }}

3.4 Copy String Array Benchmark

In this step, I will create aCopyStringArrayBenchmark class which utilizes the JMH to show the performance benchmark when copying an integer array viaSystem.arraycopy,Arrays.copyOf,Arrays.copyOfRange,Stream.toArray, andObject.clone.

CopyStringArrayBenchmark.java

package org.jcg.zheng;import java.util.Arrays;import java.util.concurrent.TimeUnit;import org.openjdk.jmh.annotations.Benchmark;import org.openjdk.jmh.annotations.BenchmarkMode;import org.openjdk.jmh.annotations.Fork;import org.openjdk.jmh.annotations.Mode;import org.openjdk.jmh.annotations.OutputTimeUnit;import org.openjdk.jmh.annotations.Scope;import org.openjdk.jmh.annotations.State;import org.openjdk.jmh.annotations.Warmup;import org.openjdk.jmh.runner.Runner;import org.openjdk.jmh.runner.RunnerException;import org.openjdk.jmh.runner.options.Options;import org.openjdk.jmh.runner.options.OptionsBuilder;@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)@State(Scope.Benchmark)@Fork(value = 1)@Warmup(iterations = 2)public class CopyStringArrayBenchmark { private String[] sourceStringArray = { "Mary", "Zheng", "Test"}; @Benchmark public String[] Arrays_String_copyOfRange() { return Arrays.copyOfRange(sourceStringArray, 0, sourceStringArray.length); } @Benchmark public String[] Arrays_Stream_String_toArray() { return Arrays.stream(sourceStringArray).toArray(String[]::new); } @Benchmark public String[] clone_StringArray() { return sourceStringArray.clone(); } @Benchmark public String[] System_arraycopy() { String[] destination = new String[3]; System.arraycopy(sourceStringArray, 0, destination, 0, 3); return destination; } @Benchmark public String[] EmptyArray() { return new String[0]; } public static void main(String[] args) { Options opt = new OptionsBuilder().include(CopyStringArrayBenchmark.class.getSimpleName()).build(); try { new Runner(opt).run() } catch (RunnerException e) { e.printStackTrace(); } }}

4. JUnit Tests

In this step, I will create several Junit test classes to demonstrate array copy for anInteger,String, andObject array. The array copy for other primitive data types:boolean,char,byte,short,long,double, andfloat are similar to theint type provided in this example.

4.1 Test Base

In this step, I will create aTestBase class to hold the common test data andsetup andcleanup methods to calculate the execution time and memory used.

  • copyStartAtZeroIndex – set the copy to start at the 0 index of the source.
  • start – anInstant variable to store the time when the test starts.
  • finish – anInstant variable to store the time when the test completes.
  • setup – a method annotated with@Before.
  • cleanup – a method marked with@After which outputs the execution time and memory used for the test method.

TestBase.java

package org.jcg.zheng;import java.time.Duration;import java.time.Instant;import org.junit.After;import org.junit.Before;import org.junit.Rule;import org.junit.rules.TestName;public class TestBase {@Rulepublic TestName name = new TestName();protected int copyStartAtZeroIndex = 0;Instant start;Instant finish;@Afterpublic void cleanup() {finish = Instant.now();Runtime after = Runtime.getRuntime();long totalAllocatedMemeryInBytes = after.totalMemory() - after.freeMemory();long totalTimeInNs = Duration.between(start, finish).toNanos();System.out.printf("\t%s completed in %d ns, used memory %d B\n", name.getMethodName(), totalTimeInNs,totalAllocatedMemeryInBytes);}@Beforepublic void setup() {start = Instant.now();}}

4.2 Copy Int Array

In this step, I will copy anInteger array viaSystem.arraycopy,Arrays.copyOf,Arrays.copyOfRange,Stream.toArray, andObject.clone methods. It will validate copied data has a different object reference for all these methods.

  • via_Arrays_copyOf – creates a copy of an integer array viaArrays.copyOf method and validates that the copied data is same as the source data.
  • via_Arrays_copyOf_big – creates a copy of an integer array whose size is larger than the source.
  • via_Arrays_copyOf_small – creates a copy of an integer array whose size is smaller than the source data.
  • via_Arrays_copyOfRange – creates a copy of an integer array and validates that the copied array’s element contains the same object reference.
  • via_Arrays_stream_toArray – creates a copy of integer array viaStream.toArray.
  • via_Object_clone – creates a copy of integer array viaObject.clone method.
  • via_System_arraycopy – creates a copy of integer array viaSystem.arraycopy.
  • validate_IntArray – validate clonedArray has a different object reference from sourceIntegerArray. Validate clonedArray has the same value for each element at the same index. Validate changing either clonedArray or sourceIntegerArray does not affect each other.

CopyIntArrayTest.java

package org.jcg.zheng;import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertFalse;import java.util.Arrays;import org.junit.Test;public class CopyIntArrayTest extends TestBase { private int[] sourceIntegerArray = { 1, 2, 3, 4, 5 }; private void validate_IntArray(int[] clonedArray) { // the copied object is a different reference assertFalse(System.identityHashCode(sourceIntegerArray) - System.identityHashCode(clonedArray) == 0); // for primitive data type, change the clonedArray element does not affect the // source array clonedArray[0] = 99; assertEquals(99, clonedArray[0]); assertEquals(1, sourceIntegerArray[0]); sourceIntegerArray[1] = 99; assertEquals(2, clonedArray[1]); } @Test public void via_Arrays_copyOf() { // since 1.6 int[] copyofArr = Arrays.copyOf(sourceIntegerArray, sourceIntegerArray.length); assertEquals(sourceIntegerArray.length, copyofArr.length); validate_IntArray(copyofArr); } @Test public void via_Arrays_copyOf_big() { int[] copyofArr = Arrays.copyOf(sourceIntegerArray, sourceIntegerArray.length + 1); assertEquals(sourceIntegerArray.length + 1, copyofArr.length); assertEquals(0, copyofArr[sourceIntegerArray.length]); validate_IntArray(copyofArr); } @Test public void via_Arrays_copyOf_small() { int[] copyofArr = Arrays.copyOf(sourceIntegerArray, sourceIntegerArray.length - 1); assertEquals(sourceIntegerArray.length - 1, copyofArr.length); validate_IntArray(copyofArr); } @Test public void via_Arrays_copyOfRange() { // since 1.6 int[] copyofArr = Arrays.copyOfRange(sourceIntegerArray, copyStartAtZeroIndex, sourceIntegerArray.length); assertEquals(sourceIntegerArray.length, copyofArr.length); assertEquals(sourceIntegerArray[0], copyofArr[0]); assertEquals(sourceIntegerArray[1], copyofArr[1]); validate_IntArray(copyofArr); } @Test public void via_Arrays_stream_toArray() { // since 1.8 int[] copyofArr = Arrays.stream(sourceIntegerArray).toArray(); assertEquals(sourceIntegerArray.length, copyofArr.length); assertEquals(1, sourceIntegerArray[0]); assertEquals(1, copyofArr[0]); validate_IntArray(copyofArr); } @Test public void via_Object_clone() { // since 1.0 int[] clonedArray = sourceIntegerArray.clone(); assertEquals(sourceIntegerArray.length, clonedArray.length); assertEquals(sourceIntegerArray[0], clonedArray[0]); assertEquals(sourceIntegerArray[1], clonedArray[1]); assertEquals(sourceIntegerArray[2], clonedArray[2]); validate_IntArray(clonedArray); } @Test public void via_System_arraycopy() { int length = 3; int[] destination = new int[length]; // since 1.0 System.arraycopy(sourceIntegerArray, copyStartAtZeroIndex, destination, copyStartAtZeroIndex, length); assertEquals(length, destination.length); assertEquals(sourceIntegerArray[copyStartAtZeroIndex], destination[0]); assertEquals(sourceIntegerArray[copyStartAtZeroIndex + 1], destination[1]); assertEquals(sourceIntegerArray[copyStartAtZeroIndex + 2], destination[2]); validate_IntArray(destination); }}

4.3 Copy String Array

In this step, I will create several test methods to copy a String array viaSystem.arraycopy,Arrays.copyOf,Arrays.copyOfRange,Stream.toArray, andObject.clone methods. We will create similar methods as you seen atCopyIntArrayTest and validate that all these methods created a copy array with a different String object with same value.

  • validate_StringArray – validate clonedArray has a different object reference from sourceStringArray. Validate clonedArray has the same value for each element at the same index. Validate changing either clonedArray or sourceStringArray does not affect each other.

CopyStringArrayTest.java

package org.jcg.zheng;import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertFalse;import java.util.Arrays;import org.junit.Test;public class CopyStringArrayTest extends TestBase {private String[] sourceStringArray = { "Mary", "Zheng", "Test" };private void validate_StringArray(String[] clonedArray) {// the copied object is a different referenceassertFalse(System.identityHashCode(sourceStringArray) - System.identityHashCode(clonedArray) == 0);// change the clonedArray element does not affect the source arrayclonedArray[0] = "Dummy";assertEquals("Dummy", clonedArray[0]);assertEquals("Mary", sourceStringArray[0]);sourceStringArray[1] = "ZhengUpdate";assertEquals("Zheng", clonedArray[1]);}@Testpublic void via_Arrays_copyOf() {// since Java 1.6String[] copyofArr = Arrays.copyOf(sourceStringArray, sourceStringArray.length - 1);assertEquals(sourceStringArray.length - 1, copyofArr.length);assertEquals(sourceStringArray[0], copyofArr[0]);assertEquals(sourceStringArray[1], copyofArr[1]);validate_StringArray(copyofArr);}@Testpublic void via_Arrays_copyOfRange() {// since Java 1.6String[] copyofArr = Arrays.copyOfRange(sourceStringArray, copyStartAtZeroIndex, sourceStringArray.length - 1);assertEquals(sourceStringArray.length - 1, copyofArr.length);assertEquals(sourceStringArray[0], copyofArr[0]);assertEquals(sourceStringArray[1], copyofArr[1]);validate_StringArray(copyofArr);}@Testpublic void via_Arrays_stream_toArray() {String[] copyofArr = Arrays.stream(sourceStringArray).toArray(String[]::new);assertEquals(sourceStringArray.length, copyofArr.length);assertEquals(sourceStringArray[0], copyofArr[0]);assertEquals(sourceStringArray[1], copyofArr[1]);validate_StringArray(copyofArr);}@Testpublic void via_Object_clone() {// since 1.0String[] clonedArray = sourceStringArray.clone();assertEquals(sourceStringArray.length, clonedArray.length);assertEquals(sourceStringArray[0], clonedArray[0]);assertEquals(sourceStringArray[1], clonedArray[1]);validate_StringArray(clonedArray);}@Testpublic void via_System_arraycopy() {int length = 3;String[] destination = new String[length];// since 1.0System.arraycopy(sourceStringArray, copyStartAtZeroIndex, destination, copyStartAtZeroIndex, length);assertEquals(sourceStringArray.length, destination.length);assertEquals(sourceStringArray[0], destination[0]);assertEquals(sourceStringArray[1], destination[1]);validate_StringArray(destination);}}

4.4 Copy Object Array

In this step, I will create several test methods to copy an object array viaSystem.arraycopy,Arrays.copyOf,Arrays.copyOfRange,Stream.toArray, andObject.clone methods.Stream.toArray is a deep copy when copying an object array. The other four methods are a “shallow copy” when copying an object array.

  • validate_shallowCopy_ObjectArray – during shallow copy, the copied array’s elements hold the same object reference to the source array’s elements, so changing the array’s elements on either copy or source affects each other.
  • validate_deepCopy_ObjectArray – during deep copy, the copied array’s elements have a different object reference from the source array’s elements, so changing the copied element doesn’t affect the source’s element, and vice versa.

CopyObjectArrayTest.java

package org.jcg.zheng;import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertFalse;import static org.junit.Assert.assertNull;import static org.junit.Assert.assertTrue;import java.util.Arrays;import org.junit.Test;public class CopyObjectArrayTest extends TestBase {private int length = 3;private DemoObject maryObject = new DemoObject('A', 1, "Mary");private DemoObject someObject = new DemoObject('B', 2, "Some data for test");private DemoObject[] sourceObjectArray = { maryObject, someObject, null };private void validate_deepCopy_ObjectArray(DemoObject[] clonedArray) {// the copied object is a different referenceassertFalse(System.identityHashCode(sourceObjectArray) - System.identityHashCode(clonedArray) == 0);assertEquals(3, clonedArray.length);// the object element reference is differentassertFalse(System.identityHashCode(maryObject) - System.identityHashCode(clonedArray[0]) == 0);assertFalse(System.identityHashCode(someObject) - System.identityHashCode(clonedArray[1]) == 0);assertEquals(maryObject, clonedArray[0]);assertEquals(someObject, clonedArray[1]);// the object change will NOT affect the other because of deep copyclonedArray[1].setName("Changed");assertEquals("Some data for test", sourceObjectArray[1].getName());sourceObjectArray[1].setNumber(99);assertEquals(2, clonedArray[1].getNumber());}private void validate_shallowCopy_ObjectArray(DemoObject[] clonedArray) {// the copied object is a different referenceassertFalse(System.identityHashCode(sourceObjectArray) - System.identityHashCode(clonedArray) == 0);// the copied object element is the same referenceassertTrue(System.identityHashCode(maryObject) - System.identityHashCode(clonedArray[0]) == 0);assertTrue(System.identityHashCode(someObject) - System.identityHashCode(clonedArray[1]) == 0);assertEquals(maryObject, clonedArray[0]);assertEquals(someObject, clonedArray[1]);// for the copied object, change one will affect the other due to object// reference is sameclonedArray[1].setName("Changed");assertEquals("Changed", sourceObjectArray[1].getName());sourceObjectArray[1].setNumber(99);assertEquals(99, clonedArray[1].getNumber());}@Testpublic void via_Arrays_copyof() {DemoObject[] clonedArray = Arrays.copyOf(sourceObjectArray, sourceObjectArray.length);assertEquals(sourceObjectArray.length, clonedArray.length);validate_shallowCopy_ObjectArray(clonedArray);}@Testpublic void via_Arrays_copyOfRange() {// since Java 1.6DemoObject[] clonedArray = Arrays.copyOfRange(sourceObjectArray, copyStartAtZeroIndex,sourceObjectArray.length - 1);assertEquals(sourceObjectArray.length - 1, clonedArray.length);validate_shallowCopy_ObjectArray(clonedArray);}@Testpublic void via_Arrays_copyOfRange_padding_null_when_dest_is_larger_then_original() {// since Java 1.6DemoObject[] clonedArray = Arrays.copyOfRange(sourceObjectArray, copyStartAtZeroIndex,sourceObjectArray.length + 1);assertEquals(sourceObjectArray.length + 1, clonedArray.length);assertNull(clonedArray[sourceObjectArray.length]);validate_shallowCopy_ObjectArray(clonedArray);}@Testpublic void via_Arrays_stream_toArray() {DemoObject[] clonedArray = Arrays.stream(sourceObjectArray).map(DemoObject::new).toArray(DemoObject[]::new);validate_deepCopy_ObjectArray(clonedArray);}@Testpublic void via_Object_clone() {// Since Java 1.0DemoObject[] clonedArray = sourceObjectArray.clone();assertEquals(sourceObjectArray.length, clonedArray.length);validate_shallowCopy_ObjectArray(clonedArray);}@Testpublic void via_System_arraycopy() {DemoObject[] destination = new DemoObject[length];// Since Java 1.0System.arraycopy(sourceObjectArray, copyStartAtZeroIndex, destination, copyStartAtZeroIndex, length);assertEquals(length, destination.length);validate_shallowCopy_ObjectArray(destination);}@Testpublic void via_System_arraycopy_padding_null_when_destination_is_bigger_than_original() {DemoObject[] destination = new DemoObject[5];// Since Java 1.0System.arraycopy(sourceObjectArray, copyStartAtZeroIndex, destination, copyStartAtZeroIndex,sourceObjectArray.length);assertNull(destination[sourceObjectArray.length]);assertNull(destination[sourceObjectArray.length + 1]);}}

4.5 Copy 2D Int Array

In this step, I will create test methods to copy a 2D integer array viaSystem.arraycopy,Arrays.copyOf,Arrays.copyOfRange,Stream.toArray, andObject.clone methods.

You will see atstep 5.1,Stream.toArray writes less code, but it takes longer time and more memory to execute.

Copy2DIntArrayTest.java

package org.jcg.zheng;import static org.junit.Assert.assertEquals;import java.util.Arrays;import org.junit.Test;public class Copy2DIntArrayTest extends TestBase {private int[][] clonedArrays;private int[][] source2DArray = { { 1, 2, 3, 4, 5 }, { 3, 4 } };protected void validate() {assertEquals(source2DArray.length, clonedArrays.length);assertEquals(source2DArray[0][0], clonedArrays[0][0]);assertEquals(source2DArray[0][1], clonedArrays[0][1]);assertEquals(source2DArray[1][0], clonedArrays[1][0]);assertEquals(source2DArray[1][1], clonedArrays[1][1]);}@Testpublic void via_Arrays_stream_toArray_lambda() {clonedArrays = Arrays.stream(source2DArray).map((int[] row) -> row.clone()).toArray((int length) -> new int[length][]);validate();}@Testpublic void via_Arrays_stream_toArray_methodReference() {clonedArrays = Arrays.stream(source2DArray).map(int[]::clone).toArray(int[][]::new);validate(); }@Testpublic void via_Object_clone() {clonedArrays = source2DArray.clone();validate();}@Testpublic void via_System_arraycopy() {clonedArrays = new int[source2DArray.length][];for (int i = 0; i < source2DArray.length; i++) {int[] aSource = source2DArray[i];clonedArrays[i] = new int[source2DArray.length];System.arraycopy(aSource, 0, clonedArrays[i], 0, source2DArray.length);}validate();}@Testpublic void via_Arrays_copyOf() {clonedArrays = new int[source2DArray.length][];for (int i = 0; i < source2DArray.length; i++) {int[] aSource = source2DArray[i];clonedArrays[i] = Arrays.copyOf(aSource, aSource.length);}validate();}}

4.6 System arraycopy

System.arraycopy will throw an exception when copying with invalid size. in this step, I will create a Junit test class to demonstrate these use cases.

  • exception_when_destination_is_null – it throws NullPointerException when the destination is a null object.
  • exception_when_copy_length_exceed_destination – it throws ArrayIndexOutOfBoundsException when the destination size is smaller than the specified range.
  • exception_when_copy_length_exceed_source – it throws ArrayIndexOutOfBoundsException when the copy range exceeds the original array index boundary.

System_arraycopyTest.java

package org.jcg.zheng;import org.junit.Test;public class System_arraycopyTest extends TestBase {private DemoObject maryObject = new DemoObject('A', 1, "Mary");private DemoObject someObject = new DemoObject('B', 2, "Some data for test");private DemoObject[] sourceObjectArray = { maryObject, someObject, null };@Test(expected = ArrayIndexOutOfBoundsException.class)public void exception_when_copy_lenght_exceed_destination() {DemoObject[] destination = new DemoObject[1];// Since Java 1.0System.arraycopy(sourceObjectArray, 0, destination, 0, destination.length + 1);}@Test(expected = ArrayIndexOutOfBoundsException.class)public void exception_when_copy_length_exceed_source() {DemoObject[] destination = new DemoObject[5];// Since Java 1.0System.arraycopy(sourceObjectArray, 0, destination, 0, sourceObjectArray.length + 1);}@Test(expected = NullPointerException.class)public void exception_when_destination_is_null() {System.arraycopy(sourceObjectArray, 0, null, 0, sourceObjectArray.length);}}

5. Demo

5.1 Junit Test Reports

I will execute the Junit tests and capture the results.

JunitOutput

------------------------------------------------------- T E S T S-------------------------------------------------------Running org.jcg.zheng.Copy2DIntArrayTest        via_Object_clone completed in 0 ns, used memory 5538560 B        via_Arrays_stream_toArray_lambda completed in 17498500 ns, used memory 6127328 B        via_Arrays_stream_toArray_methodReference completed in 999700 ns, used memory 6291456 B        via_System_arraycopy completed in 0 ns, used memory 6586512 B        via_Arrays_copyOf completed in 0 ns, used memory 6978464 BTests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.248 secRunning org.jcg.zheng.CopyIntArrayTest        via_Object_clone completed in 0 ns, used memory 7340032 B        via_Arrays_copyOfRange completed in 0 ns, used memory 7684264 B        via_Arrays_copyOf_small completed in 0 ns, used memory 8076216 B        via_Arrays_stream_toArray completed in 3999500 ns, used memory 8420448 B        via_Arrays_copyOf_big completed in 0 ns, used memory 8764680 B        via_System_arraycopy completed in 500800 ns, used memory 9108912 B        via_Arrays_copyOf completed in 500100 ns, used memory 9469024 BTests run: 7, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 secRunning org.jcg.zheng.CopyObjectArrayTest        via_Arrays_copyOfRange_padding_null_when_dest_is_larger_then_original completed in 0 ns, used memory 9878312 B        via_Object_clone completed in 500400 ns, used memory 10270264 B        via_System_arraycopy_padding_null_when_destination_is_bigger_than_original completed in 0 ns, used memory 10614496 B        via_Arrays_copyOfRange completed in 999600 ns, used memory 10958728 B        via_Arrays_stream_toArray completed in 1998500 ns, used memory 11350680 B        via_System_arraycopy completed in 0 ns, used memory 11712248 B        via_Arrays_copyof completed in 0 ns, used memory 12056480 BTests run: 7, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.01 secRunning org.jcg.zheng.CopyStringArrayTest        via_Object_clone completed in 0 ns, used memory 12448432 B        via_Arrays_copyOfRange completed in 0 ns, used memory 13054424 B        via_Arrays_stream_toArray completed in 4000700 ns, used memory 13201952 B        via_System_arraycopy completed in 0 ns, used memory 13546184 B        via_Arrays_copyOf completed in 0 ns, used memory 13907752 BTests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.021 secRunning org.jcg.zheng.System_arraycopyTest        exception_when_destination_is_null completed in 0 ns, used memory 14564408 B        exception_when_copy_length_exceed_source completed in 500400 ns, used memory 14662760 B        exception_when_copy_lenght_exceed_destination completed in 498800 ns, used memory 1963368 BTests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.006 secResults :Tests run: 27, Failures: 0, Errors: 0, Skipped: 0

Note:

  • When copying a 2D integer array,Object.clone method is the fastest and consumes the least memory. Please refer to line 05-09.
  • When copying an integer array,Object.clone method is the fastest and consumes the least memory. Please refer to line 12-18.
  • When copying an object array,Array.copyofRange method is the fastest and consumers the least memory. Please refer to line 21-27.
  • When copying a String array,Object.clone method is the fastest and consumes the least memory. Please refer to line 30-34.

5.2 JMH Performance Benchmark Reports

I will execute the two benchmark classes and capture the output here.

JMH Benchmark Output

Result "org.jcg.zheng.CopyIntArrayBenchmark.clone_IntArray":  19.686 ±(99.9%) 9.409 ns/op [Average]  (min, avg, max) = (18.463, 19.686, 24.053), stdev = 2.444  CI (99.9%): [10.276, 29.095] (assumes normal distribution)# Run complete. Total time: 00:05:56REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up onwhy the numbers are the way they are. Use profilers (see -prof, -lprof), design factorialexperiments, perform baseline and negative tests that provide experimental control, make surethe benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.Do not assume the numbers tell you what you want them to tell.Benchmark                                        Mode  Cnt   Score    Error  UnitsCopyIntArrayBenchmark.Arrays_Stream_Int_toArray  avgt    5  94.195 ± 25.917  ns/opCopyIntArrayBenchmark.Arrays_int_copyOfRange     avgt    5  28.460 ± 18.121  ns/opCopyIntArrayBenchmark.EmptyArray                 avgt    5  12.399 ±  9.217  ns/opCopyIntArrayBenchmark.System_arraycopy           avgt    5  14.454 ±  7.854  ns/opCopyIntArrayBenchmark.clone_IntArray             avgt    5  19.686 ±  9.409  ns/opResult "org.jcg.zheng.CopyStringArray.clone_StringArray":  16.729 ±(99.9%) 1.157 ns/op [Average]  (min, avg, max) = (16.305, 16.729, 17.021), stdev = 0.300  CI (99.9%): [15.572, 17.886] (assumes normal distribution)# Run complete. Total time: 00:05:55REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up onwhy the numbers are the way they are. Use profilers (see -prof, -lprof), design factorialexperiments, perform baseline and negative tests that provide experimental control, make surethe benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.Do not assume the numbers tell you what you want them to tell.Benchmark                                     Mode  Cnt   Score    Error  UnitsCopyStringArray.Arrays_Stream_String_toArray  avgt    5  84.724 ± 55.931  ns/opCopyStringArray.Arrays_String_copyOfRange     avgt    5  16.286 ±  2.151  ns/opCopyStringArray.EmptyArray                    avgt    5   7.368 ±  1.201  ns/opCopyStringArray.System_arraycopy              avgt    5  10.444 ±  1.720  ns/opCopyStringArray.clone_StringArray             avgt    5  16.729 ±  1.157  ns/op

Note:System.arraycopy is the best method under the performance testing.

6. Java Copy Array – Summary

In this example, we demonstrated how to copy an integer array with five methods:System.arraycopy,Object.clone,Arrays.copyOf,Arrays.copyOfRange, andStream.toArray.

We demonstrated thatStream.toArray is a deep copy when copying an object array. The other four methods are a “shallow copy” when copying an object array.

We compared the execution time and memory used for these methods as well as the performance benchmark. We found out thatSystem.arraycopy has the least amount of average execution time with benchmark tests andObject.clone is the fastest method using the least amount of memory under unit tests.

7. Download the Source Code

This example consists of a Maven project to copy array java.

Download
You can download the full source code of this example here:Java Copy Array Example

Last updated on Sept. 30, 2019

Do you want to know how to develop your skillset to become aJava Rockstar?
Subscribe to our newsletter to start Rockingright now!
To get you started we give you our best selling eBooks forFREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to theTerms andPrivacy Policy

Thank you!

We will contact you soon.

Photo of Mary ZhengMary ZhengApril 2nd, 2019Last Updated: July 6th, 2022
1 160 15 minutes read
Photo of Mary Zheng

Mary Zheng

Mary has graduated from Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She works as a senior Software Engineer in the telecommunications sector where she acts as a leader and works with others to design, implement, and monitor the software solution.

    Related Articles

    Bipartite Graph

    Java not equal Example

    January 17th, 2020
    Bipartite Graph

    Java API Tutorial

    October 26th, 2020
    Bipartite Graph

    Java Struct Example

    January 8th, 2020
    Bipartite Graph

    Java Node Example

    November 20th, 2019
    Bipartite Graph

    Java Swing MVC Example

    January 26th, 2016
    Bipartite Graph

    How to call a method in Java

    December 26th, 2019
    Subscribe
    Notify of
    guest
    I agree to theTerms andPrivacy Policy
    The comment form collects your name, email and content to allow us keep track of the comments placed on the website. Please read and accept our website Terms and Privacy Policy to post a comment.

    I agree to theTerms andPrivacy Policy
    The comment form collects your name, email and content to allow us keep track of the comments placed on the website. Please read and accept our website Terms and Privacy Policy to post a comment.