代码之家  ›  专栏  ›  技术社区  ›  Paul Gregoire

在Java中最快和最有效的字节数组转换为29位整数

  •  0
  • Paul Gregoire  · 技术社区  · 14 年前

    由于29位整数在AMF中很流行,所以我想合并已知的最快/最好的例程。我们的库中目前有两个例程,可以在IDeone上进行实时测试 http://ideone.com/KNmYT
    这是快速参考资料的来源

    public static int readMediumInt(ByteBuffer in) {
        ByteBuffer buf = ByteBuffer.allocate(4);
        buf.put((byte) 0x00);
        buf.put(in.get());
        buf.put(in.get());
        buf.put(in.get());
        buf.flip();
        return buf.getInt();
    }

    public static int readmediumint2(byteBuffer-In){ byte[]bytes=新字节[3]; 获取(字节); int瓦尔=0; val+=字节[0]*256*256; val+=字节[1]*256; val+=字节[2]; 如果(VAL<0){ VAL+=256; } 返回瓦尔; }

    3 回复  |  直到 14 年前
        1
  •  2
  •   erickson    14 年前

    通常我会用位操作来完成这项工作。第二个版本最终可能会被JVM优化到与此类似的程度,但是还不能确定。现在,根据您的示例,这只是24位,但问题是说“29位整数”。我不确定你到底想要什么。

    public static int readMediumInt(ByteBuffer buf) {
      return ((buf.get() & 0xFF) << 16) 
           | ((buf.get() & 0xFF) <<  8)
           | ((buf.get() & 0xFF);
    }
    
        2
  •  2
  •   Tom Anderson    14 年前

    如果您确实想读取AMF 29位整数,那么应该执行该操作(假设我正确理解了格式):

    private static int readMediumInt(ByteBuffer buf) {
        int b0, b1, b2;
        if ((b0 = buf.get()) >= 0) return b0;
        if ((b1 = buf.get()) >= 0) return ((b0 << 7) & ((~(-1 << 7)) << 7)) | b1;
        if ((b2 = buf.get()) >= 0) return ((b0 << 14) & ((~(-1 << 7)) << 14)) | ((b1 << 7) & ((~(-1 << 7)) << 7)) | b2;
        return ((b0 << 22) & ((~(-1 << 7)) << 22)) | ((b1 << 15) & ((~(-1 << 7)) << 15)) | ((b2 << 8) & ((~(-1 << 7)) << 8)) | (buf.get() & 0xff);
    }
    
        3
  •  1
  •   Thomas Mueller    14 年前

    最重要的更改是避免在方法中分配对象。顺便说一下,你的微基准没有重置“开始”,所以第二个结果包括第一个方法所用的时间。另外,您需要多次运行微基准测试,否则及时编译器就没有机会运行了。我建议使用类似于

    public static int readMediumInt3(ByteBuffer buf) {
        return ((buf.get() & 0xff) << 16) + 
                ((buf.get() & 0xff) << 8) + 
                ((buf.get() & 0xff));
    }
    

    完整的代码是:

    import java.nio.ByteBuffer;
    
    public class Main {
    
        public static int readMediumInt(ByteBuffer in) {
            ByteBuffer buf = ByteBuffer.allocate(4);
            buf.put((byte) 0x00);
            buf.put(in.get());
            buf.put(in.get());
            buf.put(in.get());
            buf.flip();
            return buf.getInt();
        }
    
        public static int readMediumInt2(ByteBuffer in) {
            byte[] bytes = new byte[3];
            in.get(bytes);
            int val = 0;
            val += bytes[0] * 256 * 256;
            val += bytes[1] * 256;
            val += bytes[2];
            if (val < 0) {
                val += 256;
            }
            return val;
        }
    
        public static int readMediumInt3(ByteBuffer buf) {
            return ((buf.get() & 0xff) << 16) + 
                    ((buf.get() & 0xff) << 8) + 
                    ((buf.get() & 0xff));
        }
    
        public static void main(String[] args) {
            Main m = new Main();
            for (int i = 0; i < 5; i++) {
                // version 1
                ByteBuffer buf = ByteBuffer.allocate(4);
                buf.putInt(424242);
                buf.flip();
                long start;
                start = System.nanoTime();
                for (int j = 0; j < 10000000; j++) {
                    buf.position(0);
                    readMediumInt(buf);
                }
                start = System.nanoTime() - start;
                System.out.printf("Ver 1: elapsed: %d ms\n", start / 1000000);
    
                // version 2
                ByteBuffer buf2 = ByteBuffer.allocate(4);
                buf2.putInt(424242);
                buf2.flip();
                start = System.nanoTime();
                for (int j = 0; j < 10000000; j++) {
                    buf2.position(0);
                    readMediumInt2(buf2);
                }
                start = System.nanoTime() - start;
                System.out.printf("Ver 2: elapsed: %d ms\n", start / 1000000);
    
                // version 3
                ByteBuffer buf3 = ByteBuffer.allocate(4);
                buf3.putInt(424242);
                buf3.flip();
                start = System.nanoTime();
                for (int j = 0; j < 10000000; j++) {
                    buf3.position(0);
                    readMediumInt3(buf3);
                }
                start = System.nanoTime() - start;
                System.out.printf("Ver 3: elapsed: %d ms\n", start / 1000000);
            }
    
        }
    }
    

    我的结果是:

    • 版本1:已用:556 ms
    • 第2版:已用:187 ms
    • 第3版:已用:3 ms