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]);
}
}
И если вы действительно требовательны к производительности, вы можете добавить отдельный счетчик или использовать сдвиг вправо вместо деления, но это достаточно просто.