-
概论
- HashMap的数据结构:
- 首先是数组存储key和value
- 存储时下标通过hash计算得到
- hash冲突时,将会使用链表存储key和value(拉链式hash)
- 当链表长度超过8时,将链表改成红黑树来存储
- hash冲突时,将会使用链表存储key和value(拉链式hash)
- HashMap的数据结构:
有问题?往下拉。。
问题
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;
}
- 大致讲解移位:
- 先来分析有关n位操作部分:先来假设n的二进制为01xxx…xxx。接着
- 对n右移1位:001xx…xxx,再位或:011xx…xxx
- 对n右移2为:00011…xxx,再位或:01111…xxx
- 此时前面已经有四个1了,再右移4位且位或可得8个1
- 同理,有8个1,右移8位肯定会让后八位也为1。
- 综上可得,该算法让最高位的1后面的位全变为1。
- 最后再让结果n+1,因为最高位以下全是1,加1后,就得到最高位1左移一位且后面全是0,得到2的幂
- 减1的原因:
- 主要是达到取值大于等于原值
- 若原值是8,1000,移位后+1得到10000,为16,但是8是合法的2的幂次数,不应该扩大
- 而 -1 再移位就能得到 8 ,结果正确。(自己算算)
-
2、为什么要采用位运算,而不是取模运算?
- 大家容易知道,计算下标时,下标范围肯定要限制于数组长度,并且下标需要均匀一些,所以需要采用取模运算
- 但是,在运算方式的速度排行中,取模运算效率是比较低的:
- 加减法 > 乘法 > 除法 > 取模
- 并且,我们可以神奇的发现,与运算可以和==取模运算等价,(当数组长度为2的幂次方)
(length - 1) & hash
等价于hash % length