我有一个byte[ ]
数组。我如何每2个字节连接(为每个人获取16位的短尺寸值)并转换为int ?
我正在使用for循环进行转换,但是我的字节数组很长,所以for循环使其变慢了。
例如:
字节数组就像:{0x00, 0x01, 0x01, 0x02, 0x03, 0x04}
我要每2个字节连接为:{0x0001, 0x0102, 0x0304}
然后得到一个 int [] 数组,例如:{ 1, 258, 772 }
,依此类推...
我可以简单地说,通过连接两个字节来获取小尺寸(16位)值,然后将其强制转换为int。
这就是我现在过世的方式,但是很慢:
byte[] buffer; // This is my byte array
int[] intBuffer = new int[buffer.length / 2];
for(int i = 0; i < buffer.length-1; i+=2){
intBuffer[i/2] = ((buffer[i] << 8) | buffer[i+1]);
}
我可以使用Java库使此过程更快吗?
谢谢。
答案 0 :(得分:0)
使用ByteBuffer一次转换两个字节。
public static int[] twoBytesToInts(byte[] bytes) {
ShortBuffer buffer = ByteBuffer.wrap(bytes).asShortBuffer();
int[] ints = new int[buffer.remaining()];
for (int i = 0; i < ints.length; i++)
ints[i] = buffer.get(i) & 0xFFFF;
return ints;
}
这使用Unsafe
一次读取两个字节,以避免移位等。
直接使用不安全来避免创建对象,您可以执行以下操作。
public static Unsafe getUnsafe() {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(null);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new AssertionError(e);
}
}
public static int[] unsafeTwoBytesToInts(byte[] bytes) {
Unsafe unsafe = getUnsafe();
int[] ints = new int[bytes.length / 2];
for (int i = 0; i < ints.length; i++)
ints[i] = Short.reverseBytes(
unsafe.getShort(bytes, i * 2 + Unsafe.ARRAY_BYTE_BASE_OFFSET)) & 0xFFFF;
return ints;
}
与此运行
public static void main(String... args) {
byte[] bytes = {0x00, 0x01, 0x01, 0x02, 0x03, 0x04};
int[] ints = twoBytesToInts(bytes);
System.out.println(Arrays.toString(ints));
int[] ints2 = unsafeTwoBytesToInts(bytes);
System.out.println(Arrays.toString(ints2));
}
打印
[1, 258, 772]
[1, 258, 772]
注意:如果您阅读Short.reverseBytes
的代码,则似乎在x86上发生了移位,JIT用固有的机器代码指令替换了此代码,以执行相同的操作。
public static int[] twoBytesToIntsOriginal(byte[] bytes) {
int[] intBuffer = new int[bytes.length / 2];
for (int i = 0; i < bytes.length - 1; i += 2) {
intBuffer[i / 2] = ((bytes[i] & 0xFF) << 8) | (bytes[i + 1] & 0xFF);
}
return intBuffer;
}
通过JMH基准运行32字节字节[]并没有太大区别。
Benchmark Mode Cnt Score Error Units
Main.original thrpt 5 45.552 ± 3.580 ops/us
Main.usingByteBuffer thrpt 5 39.968 ± 9.818 ops/us
Main.usingUnsafe thrpt 5 60.660 ± 9.234 ops/us
对于大型数组,创建ByteBuffer和ShortBuffer的成本将不再那么重要,但这也指出了另一种加快解决方案的方法,即重用int[]
而是返回长度。
public static int unsafeTwoBytesToInts(byte[] bytes, int[] ints) {
int len = bytes.length / 2;
for (int i = 0; i < len; i++)
ints[i] = Short.reverseBytes(
unsafe.getShort(bytes, i * 2L + Unsafe.ARRAY_BYTE_BASE_OFFSET)) & 0xFFFF;
return len;
}
的吞吐量
Main.usingUnsafe thrpt 5 75.268 ± 9.119 ops/us