Java 哪个更有效:System.arraycopy 还是 Arrays.copyOf?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2589741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is more efficient: System.arraycopy or Arrays.copyOf?
提问by Sawyer
The toArray
method in ArrayList
, Bloch uses both System.arraycopy
and Arrays.copyOf
to copy an array.
中的toArray
方法ArrayList
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;
}
How can I compare these two copy methods and when should I use which?
如何比较这两种复制方法,何时应该使用哪种?
采纳答案by Thilo
The difference is that Arrays.copyOf
does not only copy elements, it also creates a new array. System.arraycopy
copies into an existing array.
不同之处在于Arrays.copyOf
不仅复制元素,它还创建一个新数组。System.arraycopy
复制到现有数组中。
Here is the source for Arrays.copyOf
, as you can see it uses System.arraycopy
internally to fill up the new array:
这是 的来源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;
}
回答by Ry4an Brase
System.arrayCopy is much faster. It's in system because it uses a direct memory copy outside of Java land. Use it when possible.
System.arrayCopy 要快得多。它在系统中,因为它使用 Java 区域之外的直接内存副本。尽可能使用它。
回答by Humphrey Bogart
System.arrayCopy
is implemented natively, and hence will be faster than any Java code. I recommend you to use it.
System.arrayCopy
是本地实现的,因此比任何 Java 代码都快。我建议你使用它。
回答by Stephen C
While System.arraycopy
is implemented natively, and is therefore could be1faster than a Java loop, it is not always as fast as you might expect. Consider this example:
虽然System.arraycopy
是本地实现的,因此可能比 Java 循环快1,但它并不总是像您预期的那样快。考虑这个例子:
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.
在这种情况下,foo
和bar
数组具有不同的基类型,因此 的实现arraycopy
必须检查复制的每个引用的类型,以确保它实际上是对 String 实例的引用。这比memcopy
数组内容的简单 C 样式要慢得多。
The other point is that Arrays.copyOf
uses System.arraycopy
under the hood. Therefore System.arraycopy
is on the face of itshould not be slower2than 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.
另一点是在引擎盖下Arrays.copyOf
使用System.arraycopy
。因此System.arraycopy
是在它的脸上不应该慢2比Arrays.copyOf
。但是你可以看到(转引自码以上),其Arrays.copyOf
在某些情况下会使用反射来创建新的数组。所以性能比较并不简单。
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!
我们正在查看来自特定 Java 版本的实现代码。这些方法可能会改变,使之前关于效率的假设无效。
我们忽略了 JIT 编译器可以对这些方法进行一些巧妙的特殊情况优化的可能性。显然这确实发生在
Arrays.copyOf
; 请参阅为什么 Arrays.copyOf 比 System.arraycopy 对于小数组快 2 倍?. 这种方法在当前一代 Java 实现中是“内在的”,这意味着 JIT 编译器将忽略 Java 源代码中的内容!
But either way, the differencebetween 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 profilingtells you that it matters.
但无论哪种方式,两个版本之间的差异O(1)
(即独立于数组大小)都相对较小。因此,我的建议是使用使您的代码最容易阅读的版本,并且如果分析告诉您它很重要,则只需担心哪个更快。
1 - It couldbe faster, but it is also possiblethat the JIT compiler does such a good job of optimizing a hand-coded loop that there is no difference.
1 - 它可能更快,但也有可能JIT 编译器在优化手动编码循环方面做得很好,以至于没有区别。
回答by gustafc
If you want an exactcopy 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:
如果您想要一个数组的精确副本(例如,如果您想要进行防御性复制),复制数组的最有效方法可能是使用数组对象的clone()
方法:
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".
我没有费心去测试它的性能,但它很有可能很快,因为它都是原生的(在调用中分配和复制),并且克隆是一种特殊的 JVM 复制对象的方式(而且它是主要是出于其他目的而邪恶)并且可能能够采取一些“捷径”。
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...
就我个人而言,clone
如果它比任何其他复制方式都慢,我仍然会使用它,因为它更容易阅读并且在写作时几乎不可能搞砸。System.arrayCopy
, 另一方面...
回答by matsev
Have you looked at the Sun's implementation of Arrays.copyOf()?
你看过 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;
}
As can be seen, it uses System.arraycopy()
internally, so the performance would be the same.
可以看出,它是System.arraycopy()
内部使用的,所以性能是一样的。
回答by Ambika
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));
}
}
回答by cyberthreat
Instead of debating, these are the actual results. Clearly, your choice will depend on how much data you want to copy.
这些是实际结果,而不是辩论。显然,您的选择将取决于您要复制的数据量。
byte[] copy performance test
byte[] 复制性能测试
10,000,000 iterations 40b array.copyOfRange: 135ms systems.arraycopy: 141ms
10,000,000 次迭代 40b array.copyOfRange:135ms systems.arraycopy:141ms
10,000,000 iterations 1000b array.copyOfRange: 1861ms systems.arraycopy: 2211ms
10,000,000 次迭代 1000b array.copyOfRange:1861ms systems.arraycopy:2211ms
10,000,000 iterations 4000b array.copyOfRange: 6315ms systems.arraycopy: 5251ms
10,000,000 次迭代 4000b array.copyOfRange:6315ms systems.arraycopy:5251ms
1,000,000 iterations 100,000b array.copyOfRange: 15,198ms systems.arraycopy: 14783ms
1,000,000 次迭代 100,000b array.copyOfRange:15,198ms systems.arraycopy:14783ms
回答by Kevin Ng
If you look at both the source code for System.arraycopy() of and Array.copyOf(), for performance.
如果您同时查看 System.arraycopy() of 和 Array.copyOf() 的源代码,以提高性能。
System.arraycopy() is C code, it operates directly on your array, it does not return any values, and because of that it should operate much faster than Array.copyOf(). Nonetheless, if you need a new array to be created or if you just need the value of the copy operation then you have to create a new array for that, set the new array length, etc... Thus, you can't do a return System.arraycopy(source, 0, destination, 0, length).
System.arraycopy() 是 C 代码,它直接在您的数组上运行,它不返回任何值,因此它的运行速度应该比 Array.copyOf() 快得多。尽管如此,如果您需要创建一个新数组,或者您只需要复制操作的值,那么您必须为此创建一个新数组,设置新数组长度等......因此,您不能这样做返回 System.arraycopy(source, 0, destination, 0, length)。
For what Array.copyOf() can do then, it make a new array for you. You can assign the return value from Array.copyOf() to an array or returning it from a method as Array.copyOf() return to you a value instead of operating directly on your destination array. Thus, your code will look much cleaner. Nonetheless, for the cost of performance, Array.copyOf() is a generic type method and it does not know ahead of time what it will be working with. Thus, it has to call Array.newInstance() or new Object() and then cast it to the input's array type.
对于 Array.copyOf() 可以做什么,它会为您创建一个新数组。您可以将 Array.copyOf() 的返回值分配给数组或从方法返回它,因为 Array.copyOf() 会返回一个值,而不是直接对目标数组进行操作。因此,您的代码看起来会更简洁。尽管如此,出于性能成本的考虑, Array.copyOf() 是一种泛型类型方法,它不提前知道它将使用什么。因此,它必须调用 Array.newInstance() 或 new Object() 然后将其转换为输入的数组类型。
So to sum up. Use System.arraycopy() because of performance. Use Array.copyOf() for cleaner code.
所以总结一下。由于性能原因,请使用 System.arraycopy()。使用 Array.copyOf() 以获得更清晰的代码。