如何在不复制的情况下将字节数组转换为整数数组

时间:2020-08-14 18:38:08

标签: java android arrays

已经有一个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中执行类似的操作(即不进行内存复制)吗?

2 个答案:

答案 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