There are several ways to copy an array :
- use the various copyOf and copyOfRange methods of the Arrays class
- probably the simplest method use System.arraycopy - useful when copying parts of an array
- call its clone method, and do a cast - the simplest style, but only a shallow clone is performed
- use a for loop - more than one line, and needs a loop index
public final class ArrayCopier {
public static void main (String... aArguments) {
String action = aArguments[0];
int numIterations = 0;
if ( aArguments.length == 2 ) {
numIterations = Integer.parseInt( aArguments[1] );
}
if ( action.equals("performance") ) {
demoPerformance( numIterations );
}
else if ( action.equals("storage") ) {
demoIndependanceOfStorage();
}
}
/**
* Display the time it takes to copy an array in various ways.
*/
private static void demoPerformance( int aNumIterations ){
Stopwatch stopwatch = new Stopwatch();
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
stopwatch.start();
copyUsingClone( numbers, aNumIterations );
stopwatch.stop();
System.out.println("Using clone: " + stopwatch);
stopwatch.start();
copyUsingArraycopy( numbers, aNumIterations );
stopwatch.stop();
System.out.println("Using System.arraycopy: " + stopwatch);
stopwatch.start();
copyUsingArraysCopyOf( numbers, aNumIterations );
stopwatch.stop();
System.out.println("Using Arrays.copyOf: " + stopwatch);
stopwatch.start();
copyUsingForLoop( numbers, aNumIterations );
stopwatch.stop();
System.out.println("Using for loop: " + stopwatch);
}
private static void copyUsingClone( int[] aArray , int aNumIterations) {
for ( int idx = 0 ; idx < aNumIterations; ++idx ) {
int[] copy = (int[])aArray.clone();
}
}
private static void copyUsingArraycopy( int[] aArray , int aNumIterations) {
for ( int idx = 0 ; idx < aNumIterations; ++idx ) {
int [] copy = new int[aArray.length];
System.arraycopy( aArray, 0, copy, 0, aArray.length );
}
}
private static void copyUsingArraysCopyOf( int[] aArray , int aNumIterations) {
for ( int idx = 0 ; idx < aNumIterations; ++idx ) {
int[] copy = Arrays.copyOf(aArray, aArray.length);
}
}
private static void copyUsingForLoop( int[] aArray , int aNumIterations) {
for ( int iterIdx = 0 ; iterIdx < aNumIterations; ++iterIdx ) {
int [] copy = new int[aArray.length];
for ( int idx = 0; idx < aArray.length; ++idx ) {
copy[idx] = aArray[idx];
}
}
}
/**
* (The for-loop and System.arraycopy styles clearly have independent
* storage, and are not exercised in this method.)
*/
private static void demoIndependanceOfStorage() {
//a clone of a one-dimensional array has independent storage int[] numbers = {1,1,1,1};
int[] numbersClone = (int[])numbers.clone();
//set 0th element to 0, and compare numbersClone[0] = 0;
System.out.println("Altered clone has NOT affected original:");
System.out.println("numbersClone[0]: " + numbersClone[0] );
System.out.println("numbers[0]: " + numbers[0] );
//the clone of a multi-dimensional array does *not* have //independant storage int[][] matrix = { {1,1}, {1,1} };
int[][] matrixClone = (int[][])matrix.clone();
//set 0-0th element to 0, and compare matrixClone[0][0] = 0;
System.out.println("Altered clone has affected original:");
System.out.println("matrixClone element 0-0:" + matrixClone[0][0]);
System.out.println("matrix element 0-0: " + matrix[0][0]);
//the clone of an array of objects as well is only shallow Date[] dates = { new Date() };
System.out.println("Original date: " + dates[0]);
Date[] datesClone = (Date[])dates.clone();
datesClone[0].setTime(0);
System.out.println("Altered clone has affected original:");
System.out.println("datesClone[0]:" + datesClone[0]);
System.out.println("dates[0]: " + dates[0]);
}
}
System.arraycopy seems to have slightly better performance. Differences between the various styles are small, however, and would often be regarded as a micro-optimization : >java -cp . -Xint ArrayCopier performance 250000
Using clone: 93 ms
Using System.arraycopy: 110 ms
Using Arrays.copyOf: 187 ms
Using for loop: 422 ms
The above example use the -Xint option to turn off the Just In Time compiler. Here, bytecodes are interpreted at runtime, but never compiled by the HotSpot compiler into native code. This provides a uniform environment for executing tests of relative execution time, since there is no "warm-up" period.
Example run demonstrating independence of storage, or lack thereof :
>java -cp . ArrayCopier storage
Altered clone has NOT affected original:
numbersClone[0]: 0
numbers[0]: 1
Altered clone has affected original:
matrixClone element 0-0:0
matrix element 0-0: 0
Original date: Mon Sep 30 15:47:58 EDT 2002
Altered clone has affected original:
datesClone[0]:Wed Dec 31 19:00:00 EST 1969
dates[0]: Wed Dec 31 19:00:00 EST 1969
0 comments:
Post a Comment