code: static <K, V> Node<K, V>[] doubleCapacity(Node<K, V>[] oldTable) {
      // TODO: don't do anything if we're already at MAX_CAPACITY
      int oldCapacity = oldTable.length;
      @SuppressWarnings("unchecked") // Arrays and generics don't get along.
      Node<K, V>[] newTable = new Node[oldCapacity * 2];
      AvlIterator<K, V> iterator = new AvlIterator<K, V>();
      AvlBuilder<K, V> leftBuilder = new AvlBuilder<K, V>();
      AvlBuilder<K, V> rightBuilder = new AvlBuilder<K, V>();
  
      // Split each tree into two trees.
      for (int i = 0; i < oldCapacity; i++) {
        Node<K, V> root = oldTable[i];
        if (root == null) {
          continue;
        }
  
        // Compute the sizes of the left and right trees.
        iterator.reset(root);
        int leftSize = 0;
        int rightSize = 0;
        for (Node<K, V> node; (node = iterator.next()) != null; ) {
          if ((node.hash & oldCapacity) == 0) {
            leftSize++;
          } else {
            rightSize++;
          }
        }
  
        // Split the tree into two.
        leftBuilder.reset(leftSize);
        rightBuilder.reset(rightSize);
        iterator.reset(root);
        for (Node<K, V> node; (node = iterator.next()) != null; ) {
          if ((node.hash & oldCapacity) == 0) {
            leftBuilder.add(node);
          } else {
            rightBuilder.add(node);
          }
        }
  
        // Populate the enlarged array with these new roots.
        newTable[i] = leftSize > 0 ? leftBuilder.root() : null;
        newTable[i + oldCapacity] = rightSize > 0 ? rightBuilder.root() : null;
      }
      return newTable;
    }
docs: Returns a new array containing the same nodes as {@code oldTable}, but with
  twice as many trees, each of (approximately) half the previous size.