在字节数组上执行正确的循环位移的最快方法是什么

时间:2012-03-22 15:23:23

标签: java performance optimization bit-manipulation

如果我有阵列:

{01101111,11110000,00001111} // {111, 240, 15}

1位移位的结果是:

{10110111,11111000,00000111} // {183, 248, 7}

数组大小不固定,移位范围为1到7(包括1和7)。目前我有以下代码(工作正常):

private static void shiftBitsRight(byte[] bytes, final int rightShifts) {
   assert rightShifts >= 1 && rightShifts <= 7;

   final int leftShifts = 8 - rightShifts;

   byte previousByte = bytes[0]; // keep the byte before modification
   bytes[0] = (byte) (((bytes[0] & 0xff) >> rightShifts) | ((bytes[bytes.length - 1] & 0xff) << leftShifts));
   for (int i = 1; i < bytes.length; i++) {
      byte tmp = bytes[i];
      bytes[i] = (byte) (((bytes[i] & 0xff) >> rightShifts) | ((previousByte & 0xff) << leftShifts));
      previousByte = tmp;
   }
}

有没有比我目前的方法更快的方法来实现这一目标?

4 个答案:

答案 0 :(得分:4)

唯一可以找到的方法是彻底基准测试,最快的实现方式因平台而异。如果您确实需要优化此工具,请使用Caliper之类的工具。

答案 1 :(得分:1)

您可以做的一件事是将(byte[a]&0xff)>>b替换为byte[a]>>>b

此外,当您离开时,您不需要&0xff

虽然可能无关紧要,但是将final添加到tmp或将声明移出循环可能会有所帮助。

另一件事可能是尝试:

int tmp=bytes[bytes.length-1];
for (int i = bytes.length-2; i >=0; i--) {
  tmp=(tmp<<8)|bytes[i];
  bytes[i] = (byte) (tmp>>>rightShifts);
 }

然后你解决字节[bytes.length-1]。

如果你迷信,反向循环也可能会有所帮助。我以前见过它。

每次循环分析:

你的:3个作业,两个班次,一个或一个演员。

我的:2个作业,两个班次,一个或一个演员。

答案 2 :(得分:0)

如果你喜欢

,你可以将它概括为longs和多位移位
// for a 1-bit rightshift:
// first rotate each byte right by one
for (i = 0; i < n; i++) b[i] = rotr(b[i], 1);
// get rightmost bit
bit = b[n-1] & 0x80;
// copy high order bit from adjacent byte
for (i = n; --i >= 1;){
    b[i] &= 0x7f;
    b[i] |= (b[i-1] & 0x80);
}
// put in the rightmost bit on the left
b[0] = (b[0] & 0x7f) | bit;

假设定义了rotr

答案 3 :(得分:0)

使用ByteBuffer.wrap获取包裹byte[]的缓冲区,然后使用ByteBuffer.asLongBuffer()获取一个视图,该视图允许您按照@建议提取和操作long NiklasB。因此利用了硬件移动较大块位的能力。