【问题标题】:Undestanding of Capacity Calculation Algorithm in HashMapHashMap中容量计算算法的理解
【发布时间】:2018-10-19 13:03:03
【问题描述】:

我很想知道HashMap中容量计算算法的工作原理。

如果我们创建所需容量为 20 的 Object HashMap,那么算法将始终计算下一个最高容量,即 (2^x >20)

下面是jdk实现.....

static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

谁能解释一下上述算法是如何工作的,每一步会发生什么。

我了解到,在每一步中,他们都将数字 2 相除并按位或对旧值进行运算。 他们这样做是因为他们必须分配下一个大于 n 的 (2^x) 值,

但是有人可以帮我解释每一步中某些数字会发生什么,我尝试调试但感觉很复杂。

我有一些实现,如下所示..

private static int calculateCapacity(int cap){

    int max_capcity = 256;
    if(cap<16){
        return 16;
    }else if(cap <32){
        return 32;
    }else if(cap <64){
        return 64;
    }else if(cap < 128){
        return 128;
    }
    return max_capcity;
}

上面的实现可以用来代替复杂的按位和右移一,这有什么意义。

【问题讨论】:

  • 值得一提的是,这在 JDK 11 int n = -1 &gt;&gt;&gt; Integer.numberOfLeadingZeros(cap - 1) 中有所改变,最后一行与 JDK 1.8 中的相同。哪个更容易理解,更少混乱。

标签: java algorithm data-structures bitwise-operators


【解决方案1】:

此算法是确定2 大于或等于给定cap 的最小幂的快速方法。

它的工作方式是计算仅设置一个位的数字,并且该位的位置高于原始数字中的所有其他位(或者如果它只有一个,则位于原始数字的最高位一位设置)。为此,它将所有小于前导位的位设置为1,然后添加1

这是一个正数的工作原理,写成001XXXXXXXXX(前导位之后的位无关紧要):

int n = cap - 1;    // will not change anything to the leading bit except
                    // if cap is already a power of 2. In that case,  
                    // we had cap = 001000000000 and now n = 000111111111 and
                    // the other lines won't change anything, we just have to
                    // do +1 in the end and we're done, n = cap;
                    // otherwise, let's assume that not every 'X' is a '0'

n |= n >>> 1;       // n >>> 1 = 0001XXXXXXX
                    // so    n = 0011XXXXXXX

n |= n >>> 2;       // n >>> 2 = 000011XXXXX
                    // so    n = 001111XXXXX

n |= n >>> 4;       //       n = 0011111111X

n |= n >>> 8;       //       n = 00111111111

n |= n >>> 16;      //       n = 00111111111

return n + 1;       //  result = 01000000000

对于负数,n 在每一行都是负数,因为符号位始终为1,因此结果将为1

【讨论】:

    猜你喜欢
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 2021-03-29
    相关资源
    最近更新 更多