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

2022-08-31 10:52:04

我想创建一个新的对象数组,将两个较小的数组放在一起。

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

我无法在这两种方法之间进行选择:它们是等效的还是更有效的(例如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]        
    }
}

唯一的区别是代码的外观吗?

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

如果:byte[],Object[],char[],它真的更快吗?在所有其他情况下,都会执行类型检查,这将是我的情况,因此是等效的...不?it is not for native types

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

现在我真的很困惑。


答案 1
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);
}

我知道JUnit测试并不是最好的基准测试,但是
testHardCopyBytes需要0.157s才能完成

testArrayCopyBytes需要0.086s才能完成。

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

编辑:
看起来System.arraycopy的性能无处不在。当使用字符串而不是字节,并且数组很小(大小为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

多么奇特!

谢谢,达伦,指出参考文献的复制方式不同。它使这个问题变得更加有趣!


答案 2

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

你不能得到它更快!


推荐