Java: самый быстрый способ преобразования байта массива bye [1000] в массив int[500]

Цель состоит в том, чтобы преобразовать каждую пару байтов как один беззнаковый 16-битный тип int. В C I определил бы массив [500] из 16-битного незапятнанного указателя int и указал бы на него массив байтов, но в Java я не знаю о таком сокращении. Я знаю, что в Java нет 16-битного типа данных, кроме char, однако это не проблема. Нам нужно только скопировать каждые два последовательных двух байта в одно целое из массива целых чисел. Таким образом, массив целых содержит значения int в диапазоне от 0 до 65535 (2^16-1).

3 ответа

Решение

Я думаю, что в Java нет хороших трюков, таких как псевдонимы, которые вы можете сделать в C. Вам придется делать это вручную:

public int[] pack(byte[] bytes) {
    int n = bytes.length >> 1;
    int[] packed = new int[n];
    for (int i = 0; i < n; ++i) {
        int i2 = i << 1;
        int b1 = bytes[i2] & 0xff;
        int b2 = bytes[i2 + 1] & 0xff;
        packed[i] = (b1 << 8) | b2;
    }
    return packed;
}

(Вероятно, это может быть немного ускорено, но, вероятно, не стоит этого за 1000 элементов, если это не сделано много.) Обратите внимание, что продвижение от byte в int требуется немного дополнительной работы, чтобы справиться с нежелательным расширением знака.

Вы можете использовать ByteBuffer, чтобы избавиться от смещения и маскировки, что вы часто ошибаетесь. (и есть подписанные и неподписанные тоже)

ByteBuffer bb = ByteBuffer.wrap(bytes);
bb.order(ByteOrder.BIG_ENDIAN);  // or LITTLE_ENDIAN
short[] shorts = new short[bytes.length/2];
for (int i=0; i<shorts.length; i++)
   shorts[i] = bb.getShort();

Примечание. Если вы действительно хотите использовать "unsigned short", в java такого нет, поэтому ваш массив должен быть целым числом. Вы бы конвертировать с помощью

for (int i=0; i<intArray.length; i++) {
   short s = bb.getShort();
   intArray[i] = s & 0xFFFF; // mask off all the high order bits
}

На самом деле в Java нет беззнакового 16-битного целочисленного типа - за исключением, может быть, char, если вы оскорбляете язык. Тем не менее, это прекрасное время для использования популярной библиотеки утилит Guava:

public short[] pack(byte[] bytes) {
   short[] result = new short[bytes.length / 2];
   for (int i = 0; i < bytes.length; i += 2) {
     result[i/2] = Shorts.fromBytes(bytes[i], bytes[i+1]);
   }
}

И если вы действительно требовательны к производительности, вы можете добавить отдельный счетчик или использовать сдвиг вправо вместо деления, но это достаточно просто.

Другие вопросы по тегам