什么是更有效的: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);
在这种情况下, foo
和bar
数组的基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)); } }