views:

295

answers:

6

The toArray method in ArrayList , Bloch uses both System.arraycopy and Arrays.copyOf to copy an array .

public <T> T[] toArray(T[] a) {
  if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

How to compare these two copy methods , when to use which ? Thanks.

+4  A: 

System.arrayCopy is much faster. It's in system because it uses a direct memory copy outside of Java land. Use it when possible.

Ry4an
But System.arraycopy only copies into an existing array. Arrays.copyOf also creates the output array for you.
Thilo
That's true, and so long as you're using System.arraycopy under the covers whatever convenience wrapper you use is just gravy.
Ry4an
+1  A: 

System.arrayCopy is implemented natively, and hence will be faster than any Java code. I recommend you to use it.

Beau Martínez
+10  A: 

The difference is that Arrays.copyOf does not only copy elements, it also creates a new array. System.arrayCopy copies into an existing array.

Here is the source for Arrays.copyOf, as you can see it uses System.arraycopy internally to fill up the new array.

  public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}
Thilo
+3  A: 

While System.arrayCopy is implemented natively, and is therefore likely to be faster than a Java loop, it is not always as fast as you might expect. Consider this example:

Object[] foo = new Object[]{...};
String[] bar = new String[foo.length];

System.arraycopy(foo, 0, bar, 0, bar.length);

In this case, the base type of the foo and bar arrays have different base types, so the implementation of arrayCopy has to check the type of every reference copied to make sure that it is actually a reference to a String instance. That is significantly slower that a simple memcopy of the array contents.

The other point is that Arrays.copyOf uses System.arraycopy under the hood, so the saving you achieve by creating a new array and filling it yourself using arraycopy would be minimal. Assuming that that is what you trying to do ...

Stephen C
+1 for pointing out the type checking that has to take place sometimes.
Thilo
+3  A: 

If you want an exact copy of an array (say, if you want to do a defensive copy), the most effective way of copying an array is probably using the array object's clone() method:

class C {
    private int[] arr;
    public C(int[] values){
        this.arr = values.clone();
    }
}

I haven't bothered to test the performance of it, but it stands a good chance to be pretty fast since it's all native (allocation and copying in call), and cloning is kind of a special JVM blessed way of copying objects (and it's mostly evil for other purposes) and is likely to be able to take some "shortcuts".

Personally, I'd still use clone if it was slower than any other way of copying, because it's easier to read and nigh-impossible to screw up when writing. System.arrayCopy, on the other hand...

gustafc
+1  A: 

Have you looked at the Sun's implementation of Arrays.copyOf()?

 public static int[] copyOf(int[] original, int newLength) {
    int[] copy = new int[newLength];
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

As can be seen, it uses System.arraycopy() internally, so the performance would be the same.

matsev