【HashMap扩容相关的蛛丝马迹】位运算与取模的奇妙关系

给定一个数保证输出一定是大于输入值的2的最小幂

  • HashMap的tableSizeFor实现了这个函数,下面是细节解析
    static final int tableSizeFor(int cap) { //假设传入3和4
    	//这里-1是为了防止cap已经是2的幂时得到cap*2的结果
        int n = cap - 1; //3变2   4变3
        //这里2的二进制就是10 | 01 也就变成了二进制的11十进制是3
       	//同样3的二进制是11 | 01 还是 11 
        n |= n >>> 1;
        //这里2的二进制就是10 | 01 也就变成了二进制的11十进制是3
       	//同样3的二进制是11 | 01 还是 11 
       	//此时传入的2变成了3,4也变成了3
       	//后续操作是针对cap较大时的操作,可以省略掉
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1
        /*神奇的地方,二进制中位全为1的数再加1就是2的幂*/;
    }

应用场景

希望只有一个 i & n就可以实现模运算的场景
例如netty的EventLoop分配
例如HashMap的hash查找分配

更多

(1)思考一下如果我希望hashmap可以一边被我遍历还一边扩容,我该怎么去递增table数组的索引?如果是缩容呢?
(2)HashMap每次扩容都是2的幂那岂不是很浪费?这样做难道仅仅因为为了优化一个取模运算?(引出平摊分析)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章