以字节格式快速(呃)比较长整数?

时间:2015-12-08 21:57:29

标签: java performance guava comparator

我有一个带有byte []键的键值存储。其中一些键将用于long(longs本身,也包括Localdate和LocalTime实例)。

我有一个很好的干净的比较器,使用标准的Java和Guava:

    @Override
    public int compare(byte[] left, byte[] right) {
        long leftLong = Longs.fromByteArray(left);
        long rightLong = Longs.fromByteArray(right);
        return Long.compare(leftLong, rightLong);
    }

但它比我想象的要慢。排序100,000个长度需要100毫秒,而排序100,000个整数需要6毫秒。

是否有更快的方法来比较两个long,可能是通过避免int转换?

(你可能想知道它是否真的需要更快。如果可能的话,因为每次搜索,扫描,插入和删除长,日期等都会被调用到商店。)

2 个答案:

答案 0 :(得分:3)

我并不感到惊讶需要很长时间:分配和销毁万亿小物件的订单似乎很费力。为什么不直接比较数组?

public int compare(byte[] left, byte[] right) {
    int cmp = 0;
    for(int i = 0; i < 8 && cmp == 0; i++) { 
       cmp = (i == 0 || (left[i] >= 0 == right[i] >= 0)) ? left[i] - right[i] : right[i] - left[i]           
    }
    return cmp;
}

答案 1 :(得分:0)

这是另一种变体。它与原始类似,但在单个循环中有效地完成了两个字节到长的转换。这提高了约20%-30%的性能。 @Dima的版本更快。

    public static int compareLongs(byte[] left, byte[] right) {
        long leftLong = 0;
        long rightLong = 0;
        for (int i = 0; i < 8; i++) {
            leftLong <<= 8;
            rightLong <<= 8;
            leftLong |= (left[i] & 0xFF);
            rightLong|= (right[i] & 0xFF);
        }
        return Long.compare(leftLong, rightLong);
    }