java: fastest way of converting a bye array byte [1000] to array int[500]
-
17-04-2021 - |
문제
The goal is to convert every pair of bytes as a single unsigned 16bit int. In C I would define an array[500] of 16bit unsinged int pointer and would point it the the array of bytes, but in java I am not aware of such short cut. I know in Java there is no 16bit data type except char, however that is not an issue. We only need to copy every two consecutive two bytes into a single int of an array of integers. So the array of integer holds values of int ranging from 0 to 65535 (2^16-1).
해결책
I think that there are no nice tricks in Java like the aliasing you can do in C. You're going to have to do this by hand:
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;
}
(This can probably be sped up a bit, but probably not worth it for 1,000 elements unless it's being done a lot.) Note that the promotion from byte
to int
requires a bit of extra work to deal with unwanted sign extension.
다른 팁
You could use ByteBuffer to spare the shifting and masking, which you often get wrong. (and there is signed vs. unsigned too)
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();
Note - if you really want an "unsigned short", there is no such thing in java, so your array would have to be of integers. You would convert using
for (int i=0; i<intArray.length; i++) {
short s = bb.getShort();
intArray[i] = s & 0xFFFF; // mask off all the high order bits
}
There isn't really an unsigned 16-bit integer type in Java -- except maybe char
, if you're feeling abusive of the language. That said, this is a wonderful time to use the popular Guava utility library:
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]);
}
}
And if you're really picky about performance, you could add a separate counter or use right shift instead of division, but that's straightforward enough.