What is more efficient: System.arraycopy or Arrays.copyOf?
Solution 1:
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;
}
Solution 2:
While System.arraycopy
is implemented natively, and is therefore could be1 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 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 than a simple C-style memcopy
of the array contents.
The other point is that Arrays.copyOf
uses System.arraycopy
under the hood. Therefore System.arraycopy
is on the face of it should not be slower2 than Arrays.copyOf
. But you can see (from the code quoted above) that Arrays.copyOf
will in some cases use reflection to create the new array. So the performance comparison is not straightforward.
There are a couple of flaws in this analysis.
We are looking at the implementation code from a specific version of Java. These methods may change, invalidating previous assumptions about efficiency.
We are ignoring the possibility that the JIT compiler could do some clever special case optimization for these methods. And it apparently this does happen with
Arrays.copyOf
; see Why is Arrays.copyOf 2 times faster than System.arraycopy for small arrays?. This method is "intrinsic" in current-generation Java implementations, which means that the JIT compiler will ignore what is in the Java source code!
But either way, the difference between the two versions is O(1)
(i.e. independent of array size) and relatively small. Therefore, my advice would be to use the version that makes your code easiest to read, and only worry about which one is faster if profiling tells you that it matters.
1 - It could be faster, but it is also possible that the JIT compiler does such a good job of optimizing a hand-coded loop that there is no difference.
Solution 3:
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...