web-dev-qa-db-ja.com

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

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

72
simon

System.arraycopy または Arrays クラスの配列関数を使用するJava.util.Arrays.copyOf。どちらも、内部でネイティブパフォーマンスを提供する必要があります。

Arrays.copyOfはおそらく読みやすさの点で有利ですが、Java 1.6。

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

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)はJDK 1.6で追加されました。

copyOf()メソッドはSystem.arrayCopy()を使用して配列のコピーを作成しますが、clone()よりも柔軟性があります。配列。

93
Zaki

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

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

他の配列のコピー操作には、System.arrayCopy/Arrays.copyOf as トムが示唆する

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

7
McDowell

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

5
mdma

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

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

3
Peter Schaeffer

System.arraycopy を使用できます

2
Artem Barger

No。Javaにはmemcpyと同等のものはありません。Javaは、代わりにmemmoveと同等です。

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

Oracle Docs

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

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);