Javaにmemcpy()に相当するものはありますか?


83

byte []があり、それを別のbyte []に​​コピーしたいと思います。ここでは単純な「C」の背景を示しているかもしれませんが、Javaのバイト配列にmemcpy()に相当するものはありますか?

回答:


86

のようなクラスのSystem.arraycopy配列関数を試して利用することができます。どちらも、内部でネイティブパフォーマンスを提供するはずです。Arraysjava.util.Arrays.copyOf

Arrays.copyOfはおそらく読みやすさの点で有利ですが、java1.6でのみ導入されました。

 byte[] src = {1, 2, 3, 4};
 byte[] dst = Arrays.copyOf(src, src.length);
 System.out.println(Arrays.toString(dst));

2番目のオプションはより「論理的」だと思います。System.arraycopy()がどこにあるのか、最も不器用な場所の1つである理由がわかりませんでした。
sinuhepop 2010

@ Sinuhe-歴史的な理由でそこにあります。
スティーブンC

30
これは正解ではありません。memcpy()はデータを割り当てず、既存のバッファーにコピーするだけです。Arrays.copyOf()は明らかに新しいメモリを割り当てます。
splinux 2016

105

System.arraycopy()を使用する

System.arraycopy(sourceArray, 
                 sourceStartIndex,
                 targetArray,
                 targetStartIndex,
                 length);

例、

String[] source = { "alpha", "beta", "gamma" };
String[] target = new String[source.length];
System.arraycopy(source, 0, target, 0, source.length);


またはArrays.copyOf()の
例を使用します。

target = Arrays.copyOf(source, length);

java.util.Arrays.copyOf(byte[] source, int length)JDK1.6で追加されました。

このcopyOf()メソッドはSystem.arrayCopy()、配列のコピーを作成するために使用しますが、配列clone()の一部のコピーを作成できるため、より柔軟性があります。


5
Arrays.copyOf()もメモリを割り当てます。あなたの例では、String [] target = new String [4];を変更した場合。次に、target = Arrays.copyOf()を使用して、String [3]である新しいターゲットを作成します。memcopyの動作ではありません。
MikeF 2016年

Arrays.copyOfは、ネイティブメソッドであるSystem.arraycopyを内部的に使用します。
GajrajTanwar19年

10

1次元配列の正確なコピーが必要な場合は、を使用しますclone()

byte[] array = { 0x0A, 0x01 };
byte[] copy = array.clone();

他の配列コピー操作については、トムが提案するようにSystem.arrayCopy/Arrays.copyOfを使用してください

一般的にcloneは避けるべきですが、これは規則の例外です。


stackoverflow.com/questions/3208899/…への承認された回答の詳細も参照してください。
アンディトーマス

5

System.arrayCopyを使用できます。ソース配列から宛先配列に要素をコピーします。Sunの実装では、手動で最適化されたアセンブラーを使用するため、これは高速です。


3

Javaには、実際にはmemcpy()のようなものがあります。Unsafeクラスには、memcpy()と本質的に同じcopyMemory()メソッドがあります。もちろん、memcpy()と同様に、メモリオーバーレイ、データ破壊などからの保護は提供されません。それが本当にmemcpy()なのかmemmove()なのかは明確ではありません。実際のアドレスから実際のアドレスに、または参照から参照にコピーするために使用できます。参照を使用する場合は、オフセットを指定する必要があることに注意してください(そうしないと、JVMはできるだけ早く停止します)。

Unsafe.copyMemory()は機能します(私の古い疲れたPCでは毎秒最大2GB)。自己責任。Unsafeクラスは、すべてのJVM実装に存在するわけではないことに注意してください。


この古代のスレッドですべてのペットのセマタリーに行って申し訳ありませんが、参照の配列を使用してそれを行う方法の例を教えてください。また、少量のデータ(1〜4 MBなど)の場合は高速ですか、それとも2GBのような大きなデータの場合は価値がありますか?
FinnTheHuman 2016年

2
sun.misc.Unsafeクラスの使用は、プライベートパッケージクラスであるため、悪い習慣「ハック」と見なされます。さらに、Java 9以降は使用できなくなるため、このクラスを使用しようとすることは、コードが予期せず破損することを懇願することと同じです。
code_dredd 2017年


2

JDK1.5以降を使用している場合

System.arraycopy()

の代わりに

Arrays.copyOfRange()

Beacuse Arrays.copyOfRange()はJDK1.6まで追加されていませんでした。

Java - “Cannot Find Symbol” error

そのバージョンのJDKでArrays.copyOfRangeを呼び出す場合。


0

byteBufferViewVarHandleまたはbyteArrayViewVarHandleを使用します。

これにより、「longs」の配列を「doubles」の配列に直接コピーでき、次のようになります。

public long[] toLongs(byte[] buf) {
    int end = buf.length >> 3;
    long[] newArray = new long[end];
    for (int ii = 0; ii < end; ++ii) {
        newArray[ii] = (long)AS_LONGS_VH.get(buf, ALIGN_OFFSET + ii << 3);
    }
}

private static final ALIGN_OFFSET = ByteBuffer.wrap(new byte[0]).alignmentOffset(8); 
private static final VarHandle AS_LONGS_VH = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.nativeOrder());

これにより、次のようなビットハッキングを実行できます。

float thefloat = 0.4;
int floatBits;
_Static_assert(sizeof theFloat == sizeof floatBits, "this bit twiddling hack requires floats to be equal in size to ints");
memcpy(&floatBits, &thefloat, sizeof floatBits);

0

いいえ。Javaにはmemcpy。に相当するものはありません。Javaにはmemmove代わりに同等のものがあります。

src引数とdest引数が同じ配列オブジェクトを参照している場合、位置srcPosからsrcPos + length-1のコンポーネントが最初に長さコンポーネントを持つ一時配列にコピーされ、次に一時配列の内容がコピーされたかのようにコピーが実行されます。宛先配列のdestPos + length-1を介してdestPosの位置にコピーされます。

Oracle Docs

同じ配列を参照する場合とSystem.arraycopy同じパフォーマンスになることはほとんどありません。通常、これは十分に高速です。memcpysrcdest

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.