在看 HashMap 源码的时候有这么一段代码java
private static final int MAXIMUM_CAPACITY = 1 << 30; private static final int tableSizeFor(int c) { int n = c - 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; }
第一眼看上去彻底看不懂,这几个右移按位或是什么意思code
运行一个例子看看blog
private static final int MAXIMUM_CAPACITY = 1 << 30; private static int tableSizeFor(int c) { int n = c - 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; } public static void main(String[] args) { System.out.println(tableSizeFor(6)); System.out.println(tableSizeFor(7)); System.out.println(tableSizeFor(10)); System.out.println(tableSizeFor(15)); System.out.println(tableSizeFor(18)); } // 输出 8 8 16 16 32
输入6,7 都是输出8源码
输入10, 15 输出16hash
输入18 输出32table
输出的都是2的指数幂,其实这个方法是用于找到大于等于输入参数的的最小的2的指数幂。为何须要这样的方法,由于hashmap的容量大小都是2的指数幂。class
以输入22为例子, n = c - 1, n 为 21hashmap
每一次右移以后与上一次的结果作按位或操做(只要有一个位是1,结果就是1),经过几回操做以后将本来二进制最高位为1的后面几位所有至1,最后再加1,获得一个2的指数幂。map
至于为何一开始要执行 n = c - 1; 这是为了防止 c 已是2的幂,若是 c 已是2的幂, 又没有执行这个减1操做,则执行完后面的几条无符号右移操做以后,返回的结果将是这个c的2倍。二进制