1. ホーム
  2. java

[解決済み] 配列のコピーにはforループではなくSystem.arraycopy(...)を使うのが良いのでしょうか?

2023-03-05 03:53:53

質問

2つの小さな配列を組み合わせて、新しいオブジェクトの配列を作成したい。

nullにはなりませんが、sizeは0でも構いません。

この2つの方法のどちらかを選ぶことができません。これらは同等なのでしょうか、それともどちらかがより効率的なのでしょうか(たとえば 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]        
    }
}

違いはコードの見た目だけ?

EDITです。 リンク先の質問ありがとうございました!しかし、未解決の議論があるようです。

本当に速いのか? it is not for native types : byte[], Object[], char[] とした場合、それ以外の場合は型チェックが実行されるので、私の場合は同等となるのですが...違うのでしょうか?

別のリンク先の質問で、彼らは次のように言っています。 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);
}

JUnitのテストがベンチマークに最適でないことは承知していますが

testHardCopyBytesは0.157秒かかりました。

そして

testArrayCopyBytes は 0.086s で完了しました。



仮想マシンに依存すると思いますが、単一の配列要素をコピーするのではなく、メモリブロックをコピーしているように見えます。これなら絶対にパフォーマンスが上がりますね。



EDITです。

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

なんて独特なんでしょう。



Darenさん、リファレンスのコピー方法が違うというご指摘ありがとうございます。おかげで、この問題がより興味深いものになりました!