使用System.arraycopy(…)比for循环复制数组更好吗?

我想要创build一个新的数组,将两个较小的数组放在一起。

它们不能为空,但大小可能为0。

我不能在这两种方法之间进行select:它们是等价的还是更高效的(例如system.arraycopy()复制整个块)?

MyObject[] things = new MyObject[publicThings.length+privateThings.length]; System.arraycopy(publicThings, 0, things, 0, publicThings.length); System.arraycopy(privateThings, 0, things, publicThings.length, privateThings.length); 

要么

 MyObject[] things = new MyObject[publicThings.length+privateThings.length]; for (int i = 0; i < things.length; i++) { if (i<publicThings.length){ things[i] = publicThings[i] } else { things[i] = privateThings[i-publicThings.length] } } 

代码的外观唯一的区别是什么?

编辑:感谢链接的问题,但他们似乎有一个未解决的讨论:

如果it is not for native types它真的更快:byte [],Object [],char []? 在所有其他情况下,执行一个types检查,这将是我的情况,所以会相当于…不是?

在另一个链接的问题,他们说, the size matters a lot ,对于大小> 24 system.arraycopy()胜,小于10,手动for循环更好…

现在我真的很困惑。

 public void testHardCopyBytes() { byte[] bytes = new byte[0x5000000]; /*~83mb buffer*/ byte[] out = new byte[bytes.length]; for(int i = 0; i < out.length; i++) { out[i] = bytes[i]; } } public void testArrayCopyBytes() { byte[] bytes = new byte[0x5000000]; /*~83mb buffer*/ byte[] out = new byte[bytes.length]; System.arraycopy(bytes, 0, out, 0, out.length); } 

我知道JUnittesting并不是真正的基准testing,但是
testHardCopyBytes花了0.157s完成

testArrayCopyBytes花了0.086s完成。

我认为这取决于虚拟机,但它看起来好像是复制内存块,而不是复制单个数组元素。 这绝对会提高性能。

编辑:
它看起来像System.arraycopy的performance是在所有的地方。 当使用string而不是字节,数组很小(大小为10)时,我得到这些结果:

  String HC: 60306 ns String AC: 4812 ns byte HC: 4490 ns byte AC: 9945 ns 

这是数组大小为0x1000000时的样子。 看起来像System.arraycopy肯定会赢得更大的数组。

  Strs HC: 51730575 ns Strs AC: 24033154 ns Bytes HC: 28521827 ns Bytes AC: 5264961 ns 

多奇怪!

谢谢,达人,指出引用复制不同。 这是一个更有趣的问题!

Arrays.copyOf(T[], int)更容易阅读。 内部它使用本地调用System.arraycopy()

你不能更快得到它!

这取决于虚拟机,但System.arraycopy应该给你最接近本机性能。

我已经工作了两年,担任embedded式系统的Java开发人员(性能是一个巨大的优先事项),无处不在的System.arraycopy可以使用,我主要使用它/看到它在现有的代码中使用。 当性能是一个问题时,总是首选循环。 如果performance不是一个大问题,我会去循环,但是。 更容易阅读。

执行像Arrays.copyOf(T[], int)这样的本地方法确实有一些开销,但并不意味着它不是像使用JNI执行一样快。

最简单的方法是写一个基准和testing。

您可以检查Arrays.copyOf(T[], int)是否比正常for循环更快。

这里的基准代码: –

 public void test(int copySize, int copyCount, int testRep) { System.out.println("Copy size = " + copySize); System.out.println("Copy count = " + copyCount); System.out.println(); for (int i = testRep; i > 0; --i) { copy(copySize, copyCount); loop(copySize, copyCount); } System.out.println(); } public void copy(int copySize, int copyCount) { int[] src = newSrc(copySize + 1); int[] dst = new int[copySize + 1]; long begin = System.nanoTime(); for (int count = copyCount; count > 0; --count) { System.arraycopy(src, 1, dst, 0, copySize); dst[copySize] = src[copySize] + 1; System.arraycopy(dst, 0, src, 0, copySize); src[copySize] = dst[copySize]; } long end = System.nanoTime(); System.out.println("Arraycopy: " + (end - begin) / 1e9 + " s"); } public void loop(int copySize, int copyCount) { int[] src = newSrc(copySize + 1); int[] dst = new int[copySize + 1]; long begin = System.nanoTime(); for (int count = copyCount; count > 0; --count) { for (int i = copySize - 1; i >= 0; --i) { dst[i] = src[i + 1]; } dst[copySize] = src[copySize] + 1; for (int i = copySize - 1; i >= 0; --i) { src[i] = dst[i]; } src[copySize] = dst[copySize]; } long end = System.nanoTime(); System.out.println("Man. loop: " + (end - begin) / 1e9 + " s"); } public int[] newSrc(int arraySize) { int[] src = new int[arraySize]; for (int i = arraySize - 1; i >= 0; --i) { src[i] = i; } return src; } 

System.arraycopy()使用JNI(Java本地接口)复制一个数组(或其中的一部分),所以它非常快,你可以在这里确认

System.arraycopy()是一个本地调用,它直接在内存中复制操作。 单个内存拷贝总是比你的for循环快