-
异、或、与–位运算二进制运算
- &两位同时为“1”,结果才为“1”,否则为0
- 1+1=1
- |参加运算的两个对象只要有一个为1,其值为1。
- 1+a=1
- ^参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
- a+(!a)=1
- a+a=0
- &两位同时为“1”,结果才为“1”,否则为0
-
hashmap
-
hashmap的数据储存结构
- Jdk 1.7由数组和链表结构组成
- Jdk 1.8之后由数组,链表和红黑树组成,当链表长度大于8时就会转成红黑树结构
-
HashMap的默认容量
- 16
-
HashMap的数组大小为什么初始空间是2的幂
- 因为只有长度是2的n次方的数,进行减一操作得到的数的二进制结果的低位才能拿到全部是1的值,再进行按位与运算就能非常快速的拿到数组的下标,并且分布是均匀的
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; } 例:14 0000 1110 n |= n >>> 1; 0000 1110 | 0000 0111 = 0000 1111 n |= n >>> 2; 0000 1111 | 0000 0011 = 0000 1111 ... n |= n >>> 16; 0000 1111 | 0000 0000 = 0000 1111
- 在进行长度计算时,右移并或运算将低位全部补1,最后一步再+1就能得到2的幂
- 因为只有长度是2的n次方的数,进行减一操作得到的数的二进制结果的低位才能拿到全部是1的值,再进行按位与运算就能非常快速的拿到数组的下标,并且分布是均匀的
-
HashMap扩容—resize
- 当capacity(容量) * load(负载因子–0.75f) > threshold(预值)时进行扩容一倍
- 1.7头插法
- 将原来的数据迁移到新的hashmap中,并且要rehash
- 数据迁移时哈希桶的链表的数据顺序进行调换
- 当多线程同时进行数据的更改时,会产生循环链表,导致死锁
- 1.8尾插法
- 通过e.hash & oldCap来判断迁移后元素的新下标,并且新的链表的顺序和之前的顺序一致,从而避免了环形链表的出现