  public static final class Builder<E> extends ImmutableCollection.Builder<E> {
    // The first `size` elements are non-null.
    @VisibleForTesting @Nullable Object[] contents;
    private int size;
    private boolean copyOnWrite;

    /**
     * Creates a new builder. The returned builder is equivalent to the builder generated by {@link
     * ImmutableList#builder}.
     */
    public Builder() {
      this(DEFAULT_INITIAL_CAPACITY);
    }

    Builder(int capacity) {
      this.contents = new @Nullable Object[capacity];
      this.size = 0;
    }

    private void ensureRoomFor(int newElements) {
      @Nullable Object[] contents = this.contents;
      int newCapacity = expandedCapacity(contents.length, size + newElements);
      // expandedCapacity handles the overflow case
      if (contents.length < newCapacity || copyOnWrite) {
        this.contents = Arrays.copyOf(contents, newCapacity);
        copyOnWrite = false;
      }
    }

    /**
     * Adds {@code element} to the {@code ImmutableList}.
     *
     * @param element the element to add
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code element} is null
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> add(E element) {
      checkNotNull(element);
      ensureRoomFor(1);
      contents[size++] = element;
      return this;
    }

    /**
     * Adds each element of {@code elements} to the {@code ImmutableList}.
     *
     * @param elements the {@code Iterable} to add to the {@code ImmutableList}
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code elements} is null or contains a null element
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> add(E... elements) {
      checkElementsNotNull(elements);
      add(elements, elements.length);
      return this;
    }

    private void add(@Nullable Object[] elements, int n) {
      ensureRoomFor(n);
      /*
       * The following call is not statically checked, since arraycopy accepts plain Object for its
       * parameters. If it were statically checked, the checker would still be OK with it, since
       * we're copying into a `contents` array whose type allows it to contain nulls. Still, it's
       * worth noting that we promise not to put nulls into the array in the first `size` elements.
       * We uphold that promise here because our callers promise that `elements` will not contain
       * nulls in its first `n` elements.
       */
      System.arraycopy(elements, 0, contents, size, n);
      size += n;
    }

    /**
     * Adds each element of {@code elements} to the {@code ImmutableList}.
     *
     * @param elements the {@code Iterable} to add to the {@code ImmutableList}
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code elements} is null or contains a null element
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> addAll(Iterable<? extends E> elements) {
      checkNotNull(elements);
      if (elements instanceof Collection) {
        Collection<?> collection = (Collection<?>) elements;
        ensureRoomFor(collection.size());
        if (collection instanceof ImmutableCollection) {
          ImmutableCollection<?> immutableCollection = (ImmutableCollection<?>) collection;
          size = immutableCollection.copyIntoArray(contents, size);
          return this;
        }
      }
      super.addAll(elements);
      return this;
    }

    /**
     * Adds each element of {@code elements} to the {@code ImmutableList}.
     *
     * @param elements the {@code Iterator} to add to the {@code ImmutableList}
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code elements} is null or contains a null element
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> addAll(Iterator<? extends E> elements) {
      super.addAll(elements);
      return this;
    }

    @CanIgnoreReturnValue
    Builder<E> combine(Builder<E> builder) {
      checkNotNull(builder);
      add(builder.contents, builder.size);
      return this;
    }

    /**
     * Returns a newly-created {@code ImmutableList} based on the contents of the {@code Builder}.
     */
    @Override
    public ImmutableList<E> build() {
      copyOnWrite = true;
      return asImmutableList(contents, size);
    }

    /**
     * Returns a newly-created {@code ImmutableList} based on the contents of the {@code Builder},
     * sorted according to the specified comparator.
