已经有一个solution,但是涉及到内存复制。我想要一个不涉及内存复制的解决方案。在这种情况下,可以确保输入字节数组(byte[]
)必须由4的倍数组成,以便可以将其转换为整数数组(int[]
)而无需填充/ reallocation。
这在C语言中非常容易实现。我想要在Java中(特别是在Android上)也能做到类似的事情。这是C版本:
// input byte array
// note that the number of bytes (char) is the multiple of 4 (i.e., sizeof(int)).
char* byte_array = calloc(100, sizeof(int));
byte_array[0] = 'a'; // 0x61
byte_array[1] = 'b'; // 0x62
byte_array[2] = 'c'; // 0x63
byte_array[3] = 'd'; // 0x64
// converting it to an integer array
// note that it does not involve memory copying
int* integer_array = (int *) byte_array;
// printing the first integer of the integer array
// it will print: 0x64636261 or 0x61626364, depending on the endianness
printf("0x%X\n", integer_array[0]);
真的有可能在Java中执行类似的操作(即不进行内存复制)吗?
答案 0 :(得分:2)
不行。
Java中的数组不能轻易地重新解释为其他类型。数组对象的内存布局包括指向数组类的指针和数组的长度。没有任何操作可让您覆盖现有数组的类指针和长度字段。
您可以使用java.nio中的“缓冲区”对象执行类似的操作,但实际上并不相同。您可以创建一个包装字节数组的ByteBuffer对象。然后,您可以从字节缓冲区中获取IntBuffer“视图”。没有数据被复制,因为这些对象只是访问字节数组中数据的视图。这会打印出0x64636261
:
byte[] byte_array = new byte[128];
byte_array[0] = 'a'; // 0x61
byte_array[1] = 'b'; // 0x62
byte_array[2] = 'c'; // 0x63
byte_array[3] = 'd'; // 0x64
ByteBuffer byteBuffer = ByteBuffer.wrap(byte_array);
// set CPU-native byte order to enable optimizations
byteBuffer.order(ByteOrder.nativeOrder());
IntBuffer intBuffer = byteBuffer.asIntBuffer();
System.out.printf("0x%X\n", intBuffer.get(0));
答案 1 :(得分:0)
您可以不复制就转换为List<Integer>
,而不是转换为int[]
。
public class ByteArrayIntList extends AbstractList<Integer> {
private final int size;
private final IntBuffer intBuffer;
public ByteArrayIntList(byte[] array) {
if (array.length % 4 != 0)
throw new IllegalArgumentException("array");
this.size = array.length / 4;
this.intBuffer = ByteBuffer.wrap(array).asIntBuffer();
}
@Override
public Integer get(int index) {
return intBuffer.get(index);
}
@Override
public Integer set(int index, Integer element) {
int oldValue = get(index);
intBuffer.put(index, element);
return oldValue;
}
@Override
public int size() {
return size;
}
}
和
byte[] byteArray = {'a', 'b', 'c', 'd'};
System.out.println(Arrays.toString(byteArray));
ByteArrayIntList list = new ByteArrayIntList(byteArray);
System.out.printf("list.get(0) = 0x%08x%n", list.get(0));
输出:
list.get(0) = 0x61626364
修改此列表将修改原始字节数组。
list.set(0, 0x12345678);
System.out.print("byteArray = ");
for (int i = 0; i < byteArray.length; ++i)
System.out.printf("0x%02x ", byteArray[i]);
System.out.println();
输出:
byteArray = 0x12 0x34 0x56 0x78
您可以将.sort()
,.stream()
和.iterator()
应用于ByteArrayIntList
。
由于ByteArrayIntList
是固定长度的列表,因此.add()
会抛出UnsupportedOperationException
。