什么是更有效的:System.arraycopy vs Arrays.copyOf?

ArrayList中的toArray方法,Bloch使用System.arraycopy和Arrays.copyOf来复制数组。

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; } 

如何比较这两种复制方式,何时使用哪种?

不同的是, Arrays.copyOf不仅复制元素,而且还创build一个新的数组。 System.arrayCopy复制到一个现有的数组中。

这里是Arrays.copyOf的源Arrays.copyOf ,你可以看到它在内部使用System.arraycopy来填充新的数组。

  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; } 

虽然System.arraycopy是本地实现的,因此可能比Java循环快1倍,但并不总是像您所期望的那样快。 考虑这个例子:

 Object[] foo = new Object[]{...}; String[] bar = new String[foo.length]; System.arraycopy(foo, 0, bar, 0, bar.length); 

在这种情况下, foobar数组的基types具有不同的基types,因此arraycopy的实现必须检查每个复制的引用的types,以确保它实际上是对String实例的引用。 这比数组内容的一个简单的C风格的memcopy慢得多。

另一点是Arrays.copyOf使用System.arraycopy ,因此通过创build一个新的数组并使用arraycopy自己填充它来节省您的Arrays.copyOf将是最小的。 假设这就是你想要做的…

我的build议是使用能让代码最简单的版本,只要分析告诉你这个问题很重要,就只能担心哪个版本更快。


1 – 它可能会更快,但JIT编译器在优化手写代码循环方面做得很好,也没有什么区别。

如果你想要一个数组的精确副本(比如说,如果你想做一个防御副本),复制一个数组的最有效的方法可能是使用数组对象的clone()方法:

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

我没有费心去testing它的性能,但它是一个很好的机会,因为它都是本地的(分配和复制调用),克隆是一种特殊的JVM复制对象的祝福方式(它是主要是为其他目的的邪恶),并有可能采取一些“捷径”。

就个人而言,如果它比任何其他复制方式都慢,我仍然会使用clone ,因为在写入时,读起来更容易,几乎不可能搞砸。 System.arrayCopy ,另一方面…

System.arrayCopy要快得多。 它在系统中,因为它使用了Java域之外的直接内存拷贝。 尽可能使用它。

你看过Sun的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; } 

可以看出,它在内部使用System.arraycopy() ,所以性能会相同。

System.arrayCopy是本地实现的,因此比任何Java代码都快。 我build议你使用它。

  class ArrayCopyDemo { public static void main(String[] args) { char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd' }; char[] copyTo = new char[7]; System.arraycopy(copyFrom, 2, copyTo, 0, 7); System.out.println(new String(copyTo)); } }