HashMap

扩容

  1. 创建新数组,数组大小是原数组的两倍大
  2. 遍历原数组,将每个数组中的元素重新rehash
    1. 如果只有一个元素就直接重新rehash
    2. 如果有多个元素,链表状态的话,用hash & 旧数组长度 (没有减一)判断最高位是0还是1
      1. 最高位为0,就放在原数组坐标的哈希槽上newTab[j] = loHead
      2. 最高位为1,直接按照旧数组的下标移动到新数组的下标上newTab[j + oldCap] = hiHead
    3. 如果是红黑树,也按照最高位位运算结果是0还是1来判断是放在旧的哈希槽上,还是新的哈希槽上。因此可能红黑树被拆开,不再满足维持红黑树的条件,这之后就要回退到链表;

      同一个哈希槽的元素并不代表他们具有相同的哈希值,而是代表他们的哈希值通过位运算得到了相同的结果-》产生了哈希冲突 扩容测试:https://blog.csdn.net/u010890358/article/details/80496144

为什么按照2的幂次进行扩容

主要是为了在取模和扩容时做优化:使用位运算更便捷,也是为了减少冲突。
扩容的时候,因为2的幂次,所以他不用再每个元素重新按照hash,==,equals这三个维度进行判断,而是直接与上旧数组的长度来判断新的元素应该存在哪里。
HashTable的初始化大小就是11,使用素数是在他的设置中能取得更少的哈希冲突