什么更有效:System.arraycopy或Arrays.copyOf?

Saw*_*yer 72 java arrays performance

Bloch中的toArray方法ArrayList使用System.arraycopyArrays.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;
}
Run Code Online (Sandbox Code Playgroud)

如何比较这两种复制方法以及何时应该使用哪种方法?

Thi*_*ilo 98

不同之处在于,Arrays.copyOf不仅复制元素,还会创建新数组.System.arraycopy复制到现有数组中.

以下是源代码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;
}
Run Code Online (Sandbox Code Playgroud)

  • Java源代码[无所谓](/sf/ask/3114111311/#comment75970318_44487304)因为内在创造了. (3认同)
  • 很明显.... Arrays.copyOf应该创建一个新的array实例,因为我们没有将其传递给它。同时将目标传递给System.arraycopy。关于速度,显然System.arraycopy应该会胜出,因为它是本机方法,最终Arrays.copyOf也调用此方法来复制数组。 (2认同)

Ste*_*n C 34

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

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

System.arraycopy(foo, 0, bar, 0, bar.length);
Run Code Online (Sandbox Code Playgroud)

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

另一点是在引擎盖下memcopy使用Arrays.copyOf,因此通过创建新阵列并使用自己填充来实现的节省System.arraycopy将是最小的.假设那就是你要做的......

我的建议是使用使您的代码最容易阅读的版本,并且如果分析告诉您重要的话,只关心哪一个更快.


1 - 它可能更快,但JIT编译器也可以很好地优化手动代码循环,没有任何区别.


gus*_*afc 13

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

class C {
    private int[] arr;
    public C(int[] values){
        this.arr = values.clone();
    }
}
Run Code Online (Sandbox Code Playgroud)

我没有费心去测试它的性能,但它很快就会很快,因为它都是原生的(在调用中分配和复制),克隆是一种特殊的JVM祝福复制对象的方式(并且它是主要是邪恶的其他目的),并可能采取一些"捷径".

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


Ry4*_*ase 12

System.arrayCopy要快得多.它在系统中,因为它使用Java土地之外的直接内存副本.尽可能使用它.

  • 并且,有些情况下`System.arrayCopy`*不能*使用直接内存副本. (4认同)
  • 这是真的,只要你在封面下使用System.arraycopy,你使用的任何方便包装都只是肉汁. (2认同)

mat*_*sev 11

你看过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;
}
Run Code Online (Sandbox Code Playgroud)

可以看出,它在System.arraycopy()内部使用,因此性能将是相同的.