Best way to Copy an array in Java

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: