【发布时间】:2011-03-20 17:45:39
【问题描述】:
我有一个字节[],想将它复制到另一个字节[]。也许我在这里展示了我简单的“C”背景,但是在 Java 中的字节数组上是否有与 memcpy() 等效的方法?
【问题讨论】:
我有一个字节[],想将它复制到另一个字节[]。也许我在这里展示了我简单的“C”背景,但是在 Java 中的字节数组上是否有与 memcpy() 等效的方法?
【问题讨论】:
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() 更灵活,因为您可以制作零件的副本一个数组。
【讨论】:
您可以尝试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));
【讨论】:
如果您只想要一维数组的精确副本,请使用clone()。
byte[] array = { 0x0A, 0x01 };
byte[] copy = array.clone();
对于其他数组复制操作,使用System.arrayCopy/Arrays.copyOf作为Tom suggests。
一般来说,应该避免clone,但这是规则的一个例外。
【讨论】:
您可以使用System.arrayCopy。它将元素从源数组复制到目标数组。 Sun 实现使用手动优化的汇编程序,因此速度很快。
【讨论】:
Java 实际上确实有类似 memcpy() 的东西。 Unsafe 类有一个与 memcpy() 基本相同的 copyMemory() 方法。当然,和 memcpy() 一样,它不提供内存覆盖、数据破坏等保护。不清楚它是真的 memcpy() 还是 memmove()。它可用于从实际地址复制到实际地址或从引用复制到引用。请注意,如果使用引用,则必须提供偏移量(否则 JVM 将尽快死亡)。
Unsafe.copyMemory() 可以正常工作(在我老旧的 PC 上每秒最多 2 GB)。使用风险自负。请注意,并非所有 JVM 实现都存在 Unsafe 类。
【讨论】:
sun.misc.Unsafe 类被认为是一种不好的做法“hack”b/c 它是一个 private 包类。另外,从 Java 9 开始,它就不再可用了,所以尝试使用这个类就等于乞求你的代码意外中断。
您可以使用System.arraycopy
【讨论】:
当你使用 JDK 1.5+ 时你应该使用
System.arraycopy()
代替
Arrays.copyOfRange()
因为 Arrays.copyOfRange() 直到 JDK 1.6 才添加。所以你可能会得到
Java - “Cannot Find Symbol” error
在该版本的 JDK 中调用 Arrays.copyOfRange 时。
【讨论】:
使用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);
【讨论】:
没有。Java 没有 memcpy 的等价物。 Java 有一个等价于 memmove 的代替。
如果 src 和 dest 参数引用同一个数组对象,则执行复制,就好像首先将位置 srcPos 到 srcPos+length-1 的组件复制到具有长度组件的临时数组,然后复制临时数组通过目标数组的 destPos+length-1 复制到位置 destPos 中。
如果src 和dest 引用同一个数组,System.arraycopy 很可能永远不会具有与memcpy 相同的性能。不过通常这会足够快。
【讨论】: