[解決済み] 配列のコピーにはforループではなくSystem.arraycopy(...)を使うのが良いのでしょうか?
質問
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さん、リファレンスのコピー方法が違うというご指摘ありがとうございます。おかげで、この問題がより興味深いものになりました!
関連
-
ブートレイヤーの初期化中にエラーが発生しました java.lang.module.FindException: モジュールが見つかりません
-
名前 'XXX' を持つ Bean の作成に失敗しました。自動依存関係の注入に失敗しました 解決方法
-
無効なメソッド宣言
-
Zipファイルの圧縮・解凍にantを使用する
-
[解決済み] Javaの「for each」ループはどのように機能するのですか?
-
[解決済み] Javaでenumを繰り返し処理するためのforループ
-
[解決済み] Androidの開発でJava 8を使うことは可能ですか?
-
[解決済み】Android UserManager.isUserAGoat()の正しい使用例?)
-
[解決済み】Javaで文字列のConcatenationよりもString.formatを使用する方が良い習慣ですか?
-
[解決済み】なぜArrayDequeはLinkedListより優れているのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
java.sql.SQLException: executeQuery()でデータ操作文を発行できません。
-
Springの設定でxsdファイルのバージョン番号を設定しない方が良い理由
-
Solve モジュールのビルドに失敗しました。Error: ENOENT: no such file or directory エラー
-
ajax コミット リソースの読み込みに失敗しました: サーバーはステータス 400 で応答しました ()
-
名前 'XXX' を持つ Bean の作成に失敗しました。自動依存関係の注入に失敗しました 解決方法
-
Junitのユニットテストはjava.lang.Testを報告します。
-
Javaがテキストファイルを読み込む
-
Java appears タイプEを囲むインスタンスがアクセスできない。
-
Web Project JavaでPropertiesファイルを読み込むと、「指定されたファイルがシステムで見つかりません」というソリューションが表示されます。
-
git pull appears現在のブランチに対するトラッキング情報がありません。