分为两步
(1)扩容:创建一个新的Entry空数组,长度是原数组的2倍
(2)ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组
为什么要重新Hash呢,直接复制过去不香么?
是因为长度扩大以后,Hash的规则也随之改变。
HashMap的扩容操作是怎么实现的? - 图1
比如原来长度(Length)是8你位运算出来的值是2 ,新的长度是16你位运算出来的值明显不一样了。

HashMap的扩容操作是怎么实现的?

①.在jdk1.8中,resize方法是在hashmap中的键值对大于阀值时或者初始化时,就调用resize方法进行扩容;

②.每次扩展的时候,都是扩展2倍;

③.扩展后Node对象的位置要么在原位置,要么移动到原偏移量两倍的位置。

在putVal()中,我们看到在这个函数里面使用到了2次resize()方法,resize()方法表示的在进行第一次初始化时会对其进行扩容,或者当该数组的实际大小大于其临界值值(第一次为12),这个时候在扩容的同时也会伴随的桶上面的元素进行重新分发,这也是JDK1.8版本的一个优化的地方,在1.7中,扩容之后需要重新去计算其Hash值,根据Hash值对其进行分发,但在1.8版本中,则是根据在同一个桶的位置中进行判断(e.hash & oldCap)是否为0,重新进行hash分配后,该元素的位置要么停留在原始位置,要么移动到原始位置+增加的数组大小这个位置上

  1. final Node<K,V>[] resize() {
  2. Node<K,V>[] oldTab = table;
  3. int oldCap = (oldTab == null) ? 0 : oldTab.length;
  4. int oldThr = threshold;
  5. int newCap, newThr = 0;
  6. if (oldCap > 0) {
  7. if (oldCap >= MAXIMUM_CAPACITY) {
  8. threshold = Integer.MAX_VALUE;
  9. return oldTab;
  10. }
  11. else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
  12. oldCap >= DEFAULT_INITIAL_CAPACITY)
  13. newThr = oldThr << 1;
  14. }
  15. else if (oldThr > 0)
  16. newCap = oldThr;
  17. else {
  18. newCap = DEFAULT_INITIAL_CAPACITY;
  19. newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
  20. }
  21. if (newThr == 0) {
  22. float ft = (float)newCap * loadFactor;
  23. newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
  24. (int)ft : Integer.MAX_VALUE);
  25. }
  26. threshold = newThr;
  27. @SuppressWarnings({"rawtypes","unchecked"})
  28. Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
  29. table = newTab;
  30. if (oldTab != null) {
  31. for (int j = 0; j < oldCap; ++j) {
  32. Node<K,V> e;
  33. if ((e = oldTab[j]) != null) {
  34. oldTab[j] = null;
  35. if (e.next == null)
  36. newTab[e.hash & (newCap - 1)] = e;
  37. else if (e instanceof TreeNode)
  38. ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
  39. else {
  40. Node<K,V> loHead = null, loTail = null;
  41. Node<K,V> hiHead = null, hiTail = null;
  42. Node<K,V> next;
  43. do {
  44. next = e.next;
  45. if ((e.hash & oldCap) == 0) {
  46. if (loTail == null)
  47. loHead = e;
  48. else
  49. loTail.next = e;
  50. loTail = e;
  51. }
  52. else {
  53. if (hiTail == null)
  54. hiHead = e;
  55. else
  56. hiTail.next = e;
  57. hiTail = e;
  58. }
  59. } while ((e = next) != null);
  60. if (loTail != null) {
  61. loTail.next = null;
  62. newTab[j] = loHead;
  63. }
  64. if (hiTail != null) {
  65. hiTail.next = null;
  66. newTab[j + oldCap] = hiHead;
  67. }
  68. }
  69. }
  70. }
  71. }
  72. return newTab;
  73. }