/*
 * Copyright (C) 2014 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.collect;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.GwtCompatible;
import com.google.common.math.IntMath;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

/**
 * An accumulator that selects the "top" {@code k} elements added to it, relative to a provided
 * comparator. "Top" can mean the greatest or the lowest elements, specified in the factory used to
 * create the {@code TopKSelector} instance.
 *
 *
If your input data is available as an {@link Iterable} or {@link Iterator}, prefer {@link
 * Ordering#leastOf(Iterable, int)}, which provides the same implementation with an interface
 * tailored to that use case.
 *
 *
This uses the same efficient implementation as {@link Ordering#leastOf(Iterable, int)},
 * offering expected O(n + k log k) performance (worst case O(n log k)) for n calls to {@link
 * #offer} and a call to {@link #topK}, with O(k) memory. In comparison, quickselect has the same
 * asymptotics but requires O(n) memory, and a {@code PriorityQueue} implementation takes O(n log
 * k). In benchmarks, this implementation performs at least as well as either implementation, and
 * degrades more gracefully for worst-case input.
 *
 *
The implementation does not necessarily use a stable sorting algorithm; when multiple
 * equivalent elements are added to it, it is undefined which will come first in the output.
 *
 * @author Louis Wasserman
 */
@GwtCompatible final class TopKSelector<T> {

  /**
   * Returns a {@code TopKSelector} that collects the lowest {@code k} elements added to it,
   * relative to the natural ordering of the elements, and returns them via {@link #topK} in
   * ascending order.
   *
   * @throws IllegalArgumentException if {@code k < 0}
   */
  public static <T extends Comparable<? super T>> TopKSelector<T> least(int k) {
    return least(k, Ordering.natural());
  }

  /**
   * Returns a {@code TopKSelector} that collects the lowest {@code k} elements added to it,
   * relative to the specified comparator, and returns them via {@link #topK} in ascending order.
   *
   * @throws IllegalArgumentException if {@code k < 0}
   */
  public static <T> TopKSelector<T> least(int k, Comparator<? super T> comparator) {
    return new TopKSelector<T>(comparator, k);
  }

  /**
   * Returns a {@code TopKSelector} that collects the greatest {@code k} elements added to it,
   * relative to the natural ordering of the elements, and returns them via {@link #topK} in
   * descending order.
   *
   * @throws IllegalArgumentException if {@code k < 0}
   */
  public static <T extends Comparable<? super T>> TopKSelector<T> greatest(int k) {
    return greatest(k, Ordering.natural());
  }

  /**
   * Returns a {@code TopKSelector} that collects the greatest {@code k} elements added to it,
   * relative to the specified comparator, and returns them via {@link #topK} in descending order.
   *
   * @throws IllegalArgumentException if {@code k < 0}
   */
  public static <T> TopKSelector<T> greatest(int k, Comparator<? super T> comparator) {
    return new TopKSelector<T>(Ordering.from(comparator).reverse(), k);
  }

  private final int k;
  private final Comparator<? super T> comparator;

  /*
   * We are currently considering the elements in buffer in the range [0, bufferSize) as candidates
   * for the top k elements. Whenever the buffer is filled, we quickselect the top k elements to the
   * range [0, k) and ignore the remaining elements.
   */
  private final T[] buffer;
  private int bufferSize;

  /**
   * The largest of the lowest k elements we've seen so far relative to this comparator. If
   * bufferSize ≥ k, then we can ignore any elements greater than this value.
   */
  @NullableDecl private T threshold;

  private TopKSelector(Comparator<? super T> comparator, int k) {
    this.comparator = checkNotNull(comparator, "comparator");
    this.k = k;
    checkArgument(k >= 0, "k must be nonnegative, was %s", k);
    this.buffer = (T[]) new Object[k * 2];
    this.bufferSize = 0;
    this.threshold = null;
  }

  /**
   * Adds {@code elem} as a candidate for the top {@code k} elements. This operation takes amortized
   * O(1) time.
   */
  public void offer(@NullableDecl T elem) {
    if (k == 0) {
      return;
    } else if (bufferSize == 0) {
      buffer[0] = elem;
      threshold = elem;
      bufferSize = 1;
    } else if (bufferSize < k) {
      buffer[bufferSize++] = elem;
      if (comparator.compare(elem, threshold) > 0) {
        threshold = elem;
      }
    } else if (comparator.compare(elem, threshold) < 0) {
      // Otherwise, we can ignore elem; we've seen k better elements.
      buffer[bufferSize++] = elem;
      if (bufferSize == 2 * k) {
        trim();
      }
    }
  }

  /**
   * Quickselects the top k elements from the 2k elements in the buffer. O(k) expected time, O(k log
   * k) worst case.
   */
  private void trim() {
    int left = 0;
    int right = 2 * k - 1;

    int minThresholdPosition = 0;
    // The leftmost position at which the greatest of the k lower elements
    // -- the new value of threshold -- might be found.

    int iterations = 0;
    int maxIterations = IntMath.log2(right - left, RoundingMode.CEILING) * 3;
    while (left < right) {
      int pivotIndex = (left + right + 1) >>> 1;

      int pivotNewIndex = partition(left, right, pivotIndex);

      if (pivotNewIndex > k) {
        right = pivotNewIndex - 1;
      } else if (pivotNewIndex < k) {
        left = Math.max(pivotNewIndex, left + 1);
        minThresholdPosition = pivotNewIndex;
      } else {
        break;
      }
      iterations++;
      if (iterations >= maxIterations) {
        // We've already taken O(k log k), let's make sure we don't take longer than O(k log k).
        Arrays.sort(buffer, left, right, comparator);
        break;
      }
    }
    bufferSize = k;

    threshold = buffer[minThresholdPosition];
    for (int i = minThresholdPosition + 1; i < k; i++) {
      if (comparator.compare(buffer[i], threshold) > 0) {
        threshold = buffer[i];
      }
    }
  }

  /**
   * Partitions the contents of buffer in the range [left, right] around the pivot element
   * previously stored in buffer[pivotValue]. Returns the new index of the pivot element,
   * pivotNewIndex, so that everything in [left, pivotNewIndex] is ≤ pivotValue and everything in
   * (pivotNewIndex, right] is greater than pivotValue.
   */
  private int partition(int left, int right, int pivotIndex) {
    T pivotValue = buffer[pivotIndex];
    buffer[pivotIndex] = buffer[right];

    int pivotNewIndex = left;
    for (int i = left; i < right; i++) {
      if (comparator.compare(buffer[i], pivotValue) < 0) {
        swap(pivotNewIndex, i);
        pivotNewIndex++;
      }
    }
    buffer[right] = buffer[pivotNewIndex];
    buffer[pivotNewIndex] = pivotValue;
    return pivotNewIndex;
  }

  private void swap(int i, int j) {
    T tmp = buffer[i];
    buffer[i] = buffer[j];
    buffer[j] = tmp;
  }

  /**
   * Adds each member of {@code elements} as a candidate for the top {@code k} elements. This
   * operation takes amortized linear time in the length of {@code elements}.
   *
   *
If all input data to this {@code TopKSelector} is in a single {@code Iterable}, prefer
   * {@link Ordering#leastOf(Iterable, int)}, which provides a simpler API for that use case.
   */
  public void offerAll(Iterable<? extends T> elements) {
    offerAll(elements.iterator());
  }

  /**
   * Adds each member of {@code elements} as a candidate for the top {@code k} elements. This
   * operation takes amortized linear time in the length of {@code elements}. The iterator is
   * consumed after this operation completes.
   *
   *
If all input data to this {@code TopKSelector} is in a single {@code Iterator}, prefer
   * {@link Ordering#leastOf(Iterator, int)}, which provides a simpler API for that use case.
   */
  public void offerAll(Iterator<? extends T> elements) {
    while (elements.hasNext()) {
      offer(elements.next());
    }
  }

  /**
   * Returns the top {@code k} elements offered to this {@code TopKSelector}, or all elements if
   * fewer than {@code k} have been offered, in the order specified by the factory used to create
   * this {@code TopKSelector}.
   *
   *
The returned list is an unmodifiable copy and will not be affected by further changes to
   * this {@code TopKSelector}. This method returns in O(k log k) time.
   */
  public List<T> topK() {
    Arrays.sort(buffer, 0, bufferSize, comparator);
    if (bufferSize > k) {
      Arrays.fill(buffer, k, buffer.length, null);
      bufferSize = k;
      threshold = buffer[k - 1];
    }
    // we have to support null elements, so no ImmutableList for us
    return Collections.unmodifiableList(Arrays.asList(Arrays.copyOf(buffer, bufferSize)));
  }
}


/*
 * Copyright (C) 2009 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.collect;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.GwtCompatible;
import com.google.common.base.MoreObjects;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.Serializable;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.checkerframework.checker.nullness.compatqual.MonotonicNonNullDecl;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

/**
 * A {@link Table} whose contents will never change, with many other important properties detailed
 * at {@link ImmutableCollection}.
 *
 *
See the Guava User Guide article on  immutable collections.
 *
 * @author Gregory Kick
 * @since 11.0
 */
@GwtCompatible
public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V>
    implements Serializable {
  /** Returns an empty immutable table. */
  @SuppressWarnings("unchecked")
  public static <R, C, V> ImmutableTable<R, C, V> of() {
    return (ImmutableTable<R, C, V>) SparseImmutableTable.EMPTY;
  }

  /** Returns an immutable table containing a single cell. */
  public static <R, C, V> ImmutableTable<R, C, V> of(R rowKey, C columnKey, V value) {
    return new SingletonImmutableTable<>(rowKey, columnKey, value);
  }

  /**
   * Returns an immutable copy of the provided table.
   *
   *
The {@link Table#cellSet()} iteration order of the provided table determines the iteration
   * ordering of all views in the returned table. Note that some views of the original table and the
   * copied table may have different iteration orders. For more control over the ordering, create a
   * {@link Builder} and call {@link Builder#orderRowsBy}, {@link Builder#orderColumnsBy}, and
   * {@link Builder#putAll}
   *
   *
Despite the method name, this method attempts to avoid actually copying the data when it is
   * safe to do so. The exact circumstances under which a copy will or will not be performed are
   * undocumented and subject to change.
   */
  public static <R, C, V> ImmutableTable<R, C, V> copyOf(
      Table<? extends R, ? extends C, ? extends V> table) {
    if (table instanceof ImmutableTable) {
      @SuppressWarnings("unchecked")
      ImmutableTable<R, C, V> parameterizedTable = (ImmutableTable<R, C, V>) table;
      return parameterizedTable;
    } else {
      return copyOf(table.cellSet());
    }
  }

  private static <R, C, V> ImmutableTable<R, C, V> copyOf(
      Iterable<? extends Cell<? extends R, ? extends C, ? extends V>> cells) {
    ImmutableTable.Builder<R, C, V> builder = ImmutableTable.builder();
    for (Cell<? extends R, ? extends C, ? extends V> cell : cells) {
      builder.put(cell);
    }
    return builder.build();
  }

  /**
   * Returns a new builder. The generated builder is equivalent to the builder created by the {@link
   * Builder#Builder() ImmutableTable.Builder()} constructor.
   */
  public static <R, C, V> Builder<R, C, V> builder() {
    return new Builder<>();
  }

  /**
   * Verifies that {@code rowKey}, {@code columnKey} and {@code value} are non-null, and returns a
   * new entry with those values.
   */
  static <R, C, V> Cell<R, C, V> cellOf(R rowKey, C columnKey, V value) {
    return Tables.immutableCell(
        checkNotNull(rowKey, "rowKey"),
        checkNotNull(columnKey, "columnKey"),
        checkNotNull(value, "value"));
  }

  /**
   * A builder for creating immutable table instances, especially {@code public static final} tables
   * ("constant tables"). Example:
   *
   *
{@code
   * static final ImmutableTable<Integer, Character, String> SPREADSHEET =
   *     new ImmutableTable.Builder<Integer, Character, String>()
   *         .put(1, 'A', "foo")
   *         .put(1, 'B', "bar")
   *         .put(2, 'A', "baz")
   *         .build();
   * }

   *
   *
By default, the order in which cells are added to the builder determines the iteration
   * ordering of all views in the returned table, with {@link #putAll} following the {@link
   * Table#cellSet()} iteration order. However, if {@link #orderRowsBy} or {@link #orderColumnsBy}
   * is called, the views are sorted by the supplied comparators.
   *
   *
For empty or single-cell immutable tables, {@link #of()} and {@link #of(Object, Object,
   * Object)} are even more convenient.
   *
   *
Builder instances can be reused - it is safe to call {@link #build} multiple times to build
   * multiple tables in series. Each table is a superset of the tables created before it.
   *
   * @since 11.0
   */
  public static final class Builder<R, C, V> {
    private final List<Cell<R, C, V>> cells = Lists.newArrayList();
    @MonotonicNonNullDecl private Comparator<? super R> rowComparator;
    @MonotonicNonNullDecl private Comparator<? super C> columnComparator;

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

    /** Specifies the ordering of the generated table's rows. */
    @CanIgnoreReturnValue
    public Builder<R, C, V> orderRowsBy(Comparator<? super R> rowComparator) {
      this.rowComparator = checkNotNull(rowComparator, "rowComparator");
      return this;
    }

    /** Specifies the ordering of the generated table's columns. */
    @CanIgnoreReturnValue
    public Builder<R, C, V> orderColumnsBy(Comparator<? super C> columnComparator) {
      this.columnComparator = checkNotNull(columnComparator, "columnComparator");
      return this;
    }

    /**
     * Associates the ({@code rowKey}, {@code columnKey}) pair with {@code value} in the built
     * table. Duplicate key pairs are not allowed and will cause {@link #build} to fail.
     */
    @CanIgnoreReturnValue
    public Builder<R, C, V> put(R rowKey, C columnKey, V value) {
      cells.add(cellOf(rowKey, columnKey, value));
      return this;
    }

    /**
     * Adds the given {@code cell} to the table, making it immutable if necessary. Duplicate key
     * pairs are not allowed and will cause {@link #build} to fail.
     */
    @CanIgnoreReturnValue
    public Builder<R, C, V> put(Cell<? extends R, ? extends C, ? extends V> cell) {
      if (cell instanceof Tables.ImmutableCell) {
        checkNotNull(cell.getRowKey(), "row");
        checkNotNull(cell.getColumnKey(), "column");
        checkNotNull(cell.getValue(), "value");
        @SuppressWarnings("unchecked") // all supported methods are covariant
        Cell<R, C, V> immutableCell = (Cell<R, C, V>) cell;
        cells.add(immutableCell);
      } else {
        put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
      }
      return this;
    }

    /**
     * Associates all of the given table's keys and values in the built table. Duplicate row key
     * column key pairs are not allowed, and will cause {@link #build} to fail.
     *
     * @throws NullPointerException if any key or value in {@code table} is null
     */
    @CanIgnoreReturnValue
    public Builder<R, C, V> putAll(Table<? extends R, ? extends C, ? extends V> table) {
      for (Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
        put(cell);
      }
      return this;
    }

    /**
     * Returns a newly-created immutable table.
     *
     * @throws IllegalArgumentException if duplicate key pairs were added
     */
    public ImmutableTable<R, C, V> build() {
      int size = cells.size();
      switch (size) {
        case 0:
          return of();
        case 1:
          return new SingletonImmutableTable<>(Iterables.getOnlyElement(cells));
        default:
          return RegularImmutableTable.forCells(cells, rowComparator, columnComparator);
      }
    }
  }

  ImmutableTable() {}

  @Override
  public ImmutableSet<Cell<R, C, V>> cellSet() {
    return (ImmutableSet<Cell<R, C, V>>) super.cellSet();
  }

  @Override
  abstract ImmutableSet<Cell<R, C, V>> createCellSet();

  @Override
  final UnmodifiableIterator<Cell<R, C, V>> cellIterator() {
    throw new AssertionError("should never be called");
  }

  @Override
  public ImmutableCollection<V> values() {
    return (ImmutableCollection<V>) super.values();
  }

  @Override
  abstract ImmutableCollection<V> createValues();

  @Override
  final Iterator<V> valuesIterator() {
    throw new AssertionError("should never be called");
  }

  /**
   * {@inheritDoc}
   *
   * @throws NullPointerException if {@code columnKey} is {@code null}
   */
  @Override
  public ImmutableMap<R, V> column(C columnKey) {
    checkNotNull(columnKey, "columnKey");
    return MoreObjects.firstNonNull(
        (ImmutableMap<R, V>) columnMap().get(columnKey), ImmutableMap.<R, V>of());
  }

  @Override
  public ImmutableSet<C> columnKeySet() {
    return columnMap().keySet();
  }

  /**
   * {@inheritDoc}
   *
   *
The value {@code Map<R, V>} instances in the returned map are {@link ImmutableMap} instances
   * as well.
   */
  @Override
  public abstract ImmutableMap<C, Map<R, V>> columnMap();

  /**
   * {@inheritDoc}
   *
   * @throws NullPointerException if {@code rowKey} is {@code null}
   */
  @Override
  public ImmutableMap<C, V> row(R rowKey) {
    checkNotNull(rowKey, "rowKey");
    return MoreObjects.firstNonNull(
        (ImmutableMap<C, V>) rowMap().get(rowKey), ImmutableMap.<C, V>of());
  }

  @Override
  public ImmutableSet<R> rowKeySet() {
    return rowMap().keySet();
  }

  /**
   * {@inheritDoc}
   *
   *
The value {@code Map<C, V>} instances in the returned map are {@link ImmutableMap} instances
   * as well.
   */
  @Override
  public abstract ImmutableMap<R, Map<C, V>> rowMap();

  @Override
  public boolean contains(@NullableDecl Object rowKey, @NullableDecl Object columnKey) {
    return get(rowKey, columnKey) != null;
  }

  @Override
  public boolean containsValue(@NullableDecl Object value) {
    return values().contains(value);
  }

  /**
   * Guaranteed to throw an exception and leave the table unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @Deprecated
  @Override
  public final void clear() {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the table unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @CanIgnoreReturnValue
  @Deprecated
  @Override
  public final V put(R rowKey, C columnKey, V value) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the table unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @Deprecated
  @Override
  public final void putAll(Table<? extends R, ? extends C, ? extends V> table) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the table unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @CanIgnoreReturnValue
  @Deprecated
  @Override
  public final V remove(Object rowKey, Object columnKey) {
    throw new UnsupportedOperationException();
  }

  /** Creates the common serialized form for this table. */
  abstract SerializedForm createSerializedForm();

  /**
   * Serialized type for all ImmutableTable instances. It captures the logical contents and
   * preserves iteration order of all views.
   */
  static final class SerializedForm implements Serializable {
    private final Object[] rowKeys;
    private final Object[] columnKeys;

    private final Object[] cellValues;
    private final int[] cellRowIndices;
    private final int[] cellColumnIndices;

    private SerializedForm(
        Object[] rowKeys,
        Object[] columnKeys,
        Object[] cellValues,
        int[] cellRowIndices,
        int[] cellColumnIndices) {
      this.rowKeys = rowKeys;
      this.columnKeys = columnKeys;
      this.cellValues = cellValues;
      this.cellRowIndices = cellRowIndices;
      this.cellColumnIndices = cellColumnIndices;
    }

    static SerializedForm create(
        ImmutableTable<?, ?, ?> table, int[] cellRowIndices, int[] cellColumnIndices) {
      return new SerializedForm(
          table.rowKeySet().toArray(),
          table.columnKeySet().toArray(),
          table.values().toArray(),
          cellRowIndices,
          cellColumnIndices);
    }

    Object readResolve() {
      if (cellValues.length == 0) {
        return of();
      }
      if (cellValues.length == 1) {
        return of(rowKeys[0], columnKeys[0], cellValues[0]);
      }
      ImmutableList.Builder<Cell<Object, Object, Object>> cellListBuilder =
          new ImmutableList.Builder<>(cellValues.length);
      for (int i = 0; i < cellValues.length; i++) {
        cellListBuilder.add(
            cellOf(rowKeys[cellRowIndices[i]], columnKeys[cellColumnIndices[i]], cellValues[i]));
      }
      return RegularImmutableTable.forOrderedComponents(
          cellListBuilder.build(), ImmutableSet.copyOf(rowKeys), ImmutableSet.copyOf(columnKeys));
    }

    private static final long serialVersionUID = 0;
  }

  final Object writeReplace() {
    return createSerializedForm();
  }
}


/*
 * Copyright (C) 2011 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.collect;

import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;

/**
 * A sorted multiset which forwards all its method calls to another sorted multiset. Subclasses
 * should override one or more methods to modify the behavior of the backing multiset as desired per
 * the decorator pattern.
 *
 *
Warning: The methods of {@code ForwardingSortedMultiset} forward
 * indiscriminately to the methods of the delegate. For example, overriding {@link
 * #add(Object, int)} alone will not change the behavior of {@link #add(Object)}, which can
 * lead to unexpected behavior. In this case, you should override {@code add(Object)} as well,
 * either providing your own implementation, or delegating to the provided {@code standardAdd}
 * method.
 *
 *
The {@code standard} methods and any collection views they return are not guaranteed to be
 * thread-safe, even when all of the methods that they depend on are thread-safe.
 *
 * @author Louis Wasserman
 */
public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E>
    implements SortedMultiset<E> {
  /** Constructor for use by subclasses. */
  protected ForwardingSortedMultiset() {}

  @Override
  protected abstract SortedMultiset<E> delegate();

  @Override
  public SortedSet<E> elementSet() {
    return (SortedSet<E>) super.elementSet();
  }

  /**
   * A sensible implementation of {@link SortedMultiset#elementSet} in terms of the following
   * methods: {@link SortedMultiset#clear}, {@link SortedMultiset#comparator}, {@link
   * SortedMultiset#contains}, {@link SortedMultiset#containsAll}, {@link SortedMultiset#count},
   * {@link SortedMultiset#firstEntry} {@link SortedMultiset#headMultiset}, {@link
   * SortedMultiset#isEmpty}, {@link SortedMultiset#lastEntry}, {@link SortedMultiset#subMultiset},
   * {@link SortedMultiset#tailMultiset}, the {@code size()} and {@code iterator()} methods of
   * {@link SortedMultiset#entrySet}, and {@link SortedMultiset#remove(Object, int)}. In many
   * situations, you may wish to override {@link SortedMultiset#elementSet} to forward to this
   * implementation or a subclass thereof.
   */
  protected class StandardElementSet extends SortedMultisets.ElementSet<E> {
    /** Constructor for use by subclasses. */
    public StandardElementSet() {
      super(ForwardingSortedMultiset.this);
    }
  }

  @Override
  public Comparator<? super E> comparator() {
    return delegate().comparator();
  }

  @Override
  public SortedMultiset<E> descendingMultiset() {
    return delegate().descendingMultiset();
  }

  /**
   * A skeleton implementation of a descending multiset view. Normally, {@link
   * #descendingMultiset()} will not reflect any changes you make to the behavior of methods such as
   * {@link #add(Object)} or {@link #pollFirstEntry}. This skeleton implementation correctly
   * delegates each of its operations to the appropriate methods of this {@code
   * ForwardingSortedMultiset}.
   *
   *
In many cases, you may wish to override {@link #descendingMultiset()} to return an instance
   * of a subclass of {@code StandardDescendingMultiset}.
   */
  protected abstract class StandardDescendingMultiset extends DescendingMultiset<E> {
    /** Constructor for use by subclasses. */
    public StandardDescendingMultiset() {}

    @Override
    SortedMultiset<E> forwardMultiset() {
      return ForwardingSortedMultiset.this;
    }
  }

  @Override
  public Entry<E> firstEntry() {
    return delegate().firstEntry();
  }

  /**
   * A sensible definition of {@link #firstEntry()} in terms of {@code entrySet().iterator()}.
   *
   *
If you override {@link #entrySet()}, you may wish to override {@link #firstEntry()} to
   * forward to this implementation.
   */
  protected Entry<E> standardFirstEntry() {
    Iterator<Entry<E>> entryIterator = entrySet().iterator();
    if (!entryIterator.hasNext()) {
      return null;
    }
    Entry<E> entry = entryIterator.next();
    return Multisets.immutableEntry(entry.getElement(), entry.getCount());
  }

  @Override
  public Entry<E> lastEntry() {
    return delegate().lastEntry();
  }

  /**
   * A sensible definition of {@link #lastEntry()} in terms of {@code
   * descendingMultiset().entrySet().iterator()}.
   *
   *
If you override {@link #descendingMultiset} or {@link #entrySet()}, you may wish to override
   * {@link #firstEntry()} to forward to this implementation.
   */
  protected Entry<E> standardLastEntry() {
    Iterator<Entry<E>> entryIterator = descendingMultiset().entrySet().iterator();
    if (!entryIterator.hasNext()) {
      return null;
    }
    Entry<E> entry = entryIterator.next();
    return Multisets.immutableEntry(entry.getElement(), entry.getCount());
  }

  @Override
  public Entry<E> pollFirstEntry() {
    return delegate().pollFirstEntry();
  }

  /**
   * A sensible definition of {@link #pollFirstEntry()} in terms of {@code entrySet().iterator()}.
   *
   *
If you override {@link #entrySet()}, you may wish to override {@link #pollFirstEntry()} to
   * forward to this implementation.
   */
  protected Entry<E> standardPollFirstEntry() {
    Iterator<Entry<E>> entryIterator = entrySet().iterator();
    if (!entryIterator.hasNext()) {
      return null;
    }
    Entry<E> entry = entryIterator.next();
    entry = Multisets.immutableEntry(entry.getElement(), entry.getCount());
    entryIterator.remove();
    return entry;
  }

  @Override
  public Entry<E> pollLastEntry() {
    return delegate().pollLastEntry();
  }

  /**
   * A sensible definition of {@link #pollLastEntry()} in terms of {@code
   * descendingMultiset().entrySet().iterator()}.
   *
   *
If you override {@link #descendingMultiset()} or {@link #entrySet()}, you may wish to
   * override {@link #pollLastEntry()} to forward to this implementation.
   */
  protected Entry<E> standardPollLastEntry() {
    Iterator<Entry<E>> entryIterator = descendingMultiset().entrySet().iterator();
    if (!entryIterator.hasNext()) {
      return null;
    }
    Entry<E> entry = entryIterator.next();
    entry = Multisets.immutableEntry(entry.getElement(), entry.getCount());
    entryIterator.remove();
    return entry;
  }

  @Override
  public SortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
    return delegate().headMultiset(upperBound, boundType);
  }

  @Override
  public SortedMultiset<E> subMultiset(
      E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) {
    return delegate().subMultiset(lowerBound, lowerBoundType, upperBound, upperBoundType);
  }

  /**
   * A sensible definition of {@link #subMultiset(Object, BoundType, Object, BoundType)} in terms of
   * {@link #headMultiset(Object, BoundType) headMultiset} and {@link #tailMultiset(Object,
   * BoundType) tailMultiset}.
   *
   *
If you override either of these methods, you may wish to override {@link
   * #subMultiset(Object, BoundType, Object, BoundType)} to forward to this implementation.
   */
  protected SortedMultiset<E> standardSubMultiset(
      E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) {
    return tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound, upperBoundType);
  }

  @Override
  public SortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
    return delegate().tailMultiset(lowerBound, boundType);
  }
}


/*
 * Copyright (C) 2012 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.common.reflect;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.collect.ForwardingMap;
import com.google.common.collect.ForwardingMapEntry;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * A mutable type-to-instance map. See also {@link ImmutableTypeToInstanceMap}.
 *
 * @author Ben Yu
 * @since 13.0
 */
@Beta
public final class MutableTypeToInstanceMap<B> extends ForwardingMap<TypeToken<? extends B>, B>
    implements TypeToInstanceMap<B> {

  private final Map<TypeToken<? extends B>, B> backingMap = Maps.newHashMap();

  @Override
  public <T extends B> @Nullable T getInstance(Class<T> type) {
    return trustedGet(TypeToken.of(type));
  }

  @Override
  public <T extends B> @Nullable T getInstance(TypeToken<T> type) {
    return trustedGet(type.rejectTypeVariables());
  }

  @Override
  @CanIgnoreReturnValue
  public <T extends B> @Nullable T putInstance(Class<T> type, @Nullable T value) {
    return trustedPut(TypeToken.of(type), value);
  }

  @Override
  @CanIgnoreReturnValue
  public <T extends B> @Nullable T putInstance(TypeToken<T> type, @Nullable T value) {
    return trustedPut(type.rejectTypeVariables(), value);
  }

  /**
   * Not supported. Use {@link #putInstance} instead.
   *
   * @deprecated unsupported operation
   * @throws UnsupportedOperationException always
   */
  @CanIgnoreReturnValue
  @Deprecated
  @Override
  public B put(TypeToken<? extends B> key, B value) {
    throw new UnsupportedOperationException("Please use putInstance() instead.");
  }

  /**
   * Not supported. Use {@link #putInstance} instead.
   *
   * @deprecated unsupported operation
   * @throws UnsupportedOperationException always
   */
  @Deprecated
  @Override
  public void putAll(Map<? extends TypeToken<? extends B>, ? extends B> map) {
    throw new UnsupportedOperationException("Please use putInstance() instead.");
  }

  @Override
  public Set<Entry<TypeToken<? extends B>, B>> entrySet() {
    return UnmodifiableEntry.transformEntries(super.entrySet());
  }

  @Override
  protected Map<TypeToken<? extends B>, B> delegate() {
    return backingMap;
  }

  @SuppressWarnings("unchecked") // value could not get in if not a T
  private <T extends B> @Nullable T trustedPut(TypeToken<T> type, @Nullable T value) {
    return (T) backingMap.put(type, value);
  }

  @SuppressWarnings("unchecked") // value could not get in if not a T
  private <T extends B> @Nullable T trustedGet(TypeToken<T> type) {
    return (T) backingMap.get(type);
  }

  private static final class UnmodifiableEntry<K, V> extends ForwardingMapEntry<K, V> {

    private final Entry<K, V> delegate;

    static <K, V> Set<Entry<K, V>> transformEntries(final Set<Entry<K, V>> entries) {
      return new ForwardingSet<Map.Entry<K, V>>() {
        @Override
        protected Set<Entry<K, V>> delegate() {
          return entries;
        }

        @Override
        public Iterator<Entry<K, V>> iterator() {
          return UnmodifiableEntry.transformEntries(super.iterator());
        }

        @Override
        public Object[] toArray() {
          return standardToArray();
        }

        @Override
        public <T> T[] toArray(T[] array) {
          return standardToArray(array);
        }
      };
    }

    private static <K, V> Iterator<Entry<K, V>> transformEntries(Iterator<Entry<K, V>> entries) {
      return Iterators.transform(
          entries,
          new Function<Entry<K, V>, Entry<K, V>>() {
            @Override
            public Entry<K, V> apply(Entry<K, V> entry) {
              return new UnmodifiableEntry<>(entry);
            }
          });
    }

    private UnmodifiableEntry(java.util.Map.Entry<K, V> delegate) {
      this.delegate = checkNotNull(delegate);
    }

    @Override
    protected Entry<K, V> delegate() {
      return delegate;
    }

    @Override
    public V setValue(V value) {
      throw new UnsupportedOperationException();
    }
  }
}


/*
 * Copyright (C) 2007 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.collect;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndex;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.collect.CollectPreconditions.checkRemove;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.math.IntMath;
import com.google.common.primitives.Ints;
import java.io.Serializable;
import java.math.RoundingMode;
import java.util.AbstractList;
import java.util.AbstractSequentialList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.RandomAccess;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Predicate;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * Static utility methods pertaining to {@link List} instances. Also see this class's counterparts
 * {@link Sets}, {@link Maps} and {@link Queues}.
 *
 *
See the Guava User Guide article on  {@code Lists}.
 *
 * @author Kevin Bourrillion
 * @author Mike Bostock
 * @author Louis Wasserman
 * @since 2.0
 */
@GwtCompatible(emulated = true)
public final class Lists {
  private Lists() {}

  // ArrayList

  /**
   * Creates a mutable, empty {@code ArrayList} instance (for Java 6 and earlier).
   *
   *
Note: if mutability is not required, use {@link ImmutableList#of()} instead.
   *
   *
Note for Java 7 and later: this method is now unnecessary and should be treated as
   * deprecated. Instead, use the {@code ArrayList} {@linkplain ArrayList#ArrayList() constructor}
   * directly, taking advantage of the new "diamond" syntax.
   */
  @GwtCompatible(serializable = true)
  public static <E> ArrayList<E> newArrayList() {
    return new ArrayList<>();
  }

  /**
   * Creates a mutable {@code ArrayList} instance containing the given elements.
   *
   *
Note: essentially the only reason to use this method is when you will need to add or
   * remove elements later. Otherwise, for non-null elements use {@link ImmutableList#of()} (for
   * varargs) or {@link ImmutableList#copyOf(Object[])} (for an array) instead. If any elements
   * might be null, or you need support for {@link List#set(int, Object)}, use {@link
   * Arrays#asList}.
   *
   *
Note that even when you do need the ability to add or remove, this method provides only a
   * tiny bit of syntactic sugar for {@code newArrayList(}{@link Arrays#asList asList}{@code
   * (...))}, or for creating an empty list then calling {@link Collections#addAll}. This method is
   * not actually very useful and will likely be deprecated in the future.
   */
  @SafeVarargs
  @GwtCompatible(serializable = true)
  public static <E> ArrayList<E> newArrayList(E... elements) {
    checkNotNull(elements); // for GWT
    // Avoid integer overflow when a large array is passed in
    int capacity = computeArrayListCapacity(elements.length);
    ArrayList<E> list = new ArrayList<>(capacity);
    Collections.addAll(list, elements);
    return list;
  }

  /**
   * Creates a mutable {@code ArrayList} instance containing the given elements; a very thin
   * shortcut for creating an empty list then calling {@link Iterables#addAll}.
   *
   *
Note: if mutability is not required and the elements are non-null, use {@link
   * ImmutableList#copyOf(Iterable)} instead. (Or, change {@code elements} to be a {@link
   * FluentIterable} and call {@code elements.toList()}.)
   *
   *
Note for Java 7 and later: if {@code elements} is a {@link Collection}, you don't
   * need this method. Use the {@code ArrayList} {@linkplain ArrayList#ArrayList(Collection)
   * constructor} directly, taking advantage of the new "diamond"
   * syntax.
   */
  @GwtCompatible(serializable = true)
  public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
    checkNotNull(elements); // for GWT
    // Let ArrayList's sizing logic work, if possible
    return (elements instanceof Collection)
        ? new ArrayList<>(Collections2.cast(elements))
        : newArrayList(elements.iterator());
  }

  /**
   * Creates a mutable {@code ArrayList} instance containing the given elements; a very thin
   * shortcut for creating an empty list and then calling {@link Iterators#addAll}.
   *
   *
Note: if mutability is not required and the elements are non-null, use {@link
   * ImmutableList#copyOf(Iterator)} instead.
   */
  @GwtCompatible(serializable = true)
  public static <E> ArrayList<E> newArrayList(Iterator<? extends E> elements) {
    ArrayList<E> list = newArrayList();
    Iterators.addAll(list, elements);
    return list;
  }

  @VisibleForTesting
  static int computeArrayListCapacity(int arraySize) {
    checkNonnegative(arraySize, "arraySize");

    // TODO(kevinb): Figure out the right behavior, and document it
    return Ints.saturatedCast(5L + arraySize + (arraySize / 10));
  }

  /**
   * Creates an {@code ArrayList} instance backed by an array with the specified initial size;
   * simply delegates to {@link ArrayList#ArrayList(int)}.
   *
   *
Note for Java 7 and later: this method is now unnecessary and should be treated as
   * deprecated. Instead, use {@code new }{@link ArrayList#ArrayList(int) ArrayList}{@code <>(int)}
   * directly, taking advantage of the new "diamond" syntax.
   * (Unlike here, there is no risk of overload ambiguity, since the {@code ArrayList} constructors
   * very wisely did not accept varargs.)
   *
   * @param initialArraySize the exact size of the initial backing array for the returned array list
   *     ({@code ArrayList} documentation calls this value the "capacity")
   * @return a new, empty {@code ArrayList} which is guaranteed not to resize itself unless its size
   *     reaches {@code initialArraySize + 1}
   * @throws IllegalArgumentException if {@code initialArraySize} is negative
   */
  @GwtCompatible(serializable = true)
  public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {
    checkNonnegative(initialArraySize, "initialArraySize"); // for GWT.
    return new ArrayList<>(initialArraySize);
  }

  /**
   * Creates an {@code ArrayList} instance to hold {@code estimatedSize} elements, plus an
   * unspecified amount of padding; you almost certainly mean to call {@link
   * #newArrayListWithCapacity} (see that method for further advice on usage).
   *
   *
Note: This method will soon be deprecated. Even in the rare case that you do want
   * some amount of padding, it's best if you choose your desired amount explicitly.
   *
   * @param estimatedSize an estimate of the eventual {@link List#size()} of the new list
   * @return a new, empty {@code ArrayList}, sized appropriately to hold the estimated number of
   *     elements
   * @throws IllegalArgumentException if {@code estimatedSize} is negative
   */
  @GwtCompatible(serializable = true)
  public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
    return new ArrayList<>(computeArrayListCapacity(estimatedSize));
  }

  // LinkedList

  /**
   * Creates a mutable, empty {@code LinkedList} instance (for Java 6 and earlier).
   *
   *
Note: if you won't be adding any elements to the list, use {@link ImmutableList#of()}
   * instead.
   *
   *
Performance note: {@link ArrayList} and {@link java.util.ArrayDeque} consistently
   * outperform {@code LinkedList} except in certain rare and specific situations. Unless you have
   * spent a lot of time benchmarking your specific needs, use one of those instead.
   *
   *
Note for Java 7 and later: this method is now unnecessary and should be treated as
   * deprecated. Instead, use the {@code LinkedList} {@linkplain LinkedList#LinkedList()
   * constructor} directly, taking advantage of the new "diamond"
   * syntax.
   */
  @GwtCompatible(serializable = true)
  public static <E> LinkedList<E> newLinkedList() {
    return new LinkedList<>();
  }

  /**
   * Creates a mutable {@code LinkedList} instance containing the given elements; a very thin
   * shortcut for creating an empty list then calling {@link Iterables#addAll}.
   *
   *
Note: if mutability is not required and the elements are non-null, use {@link
   * ImmutableList#copyOf(Iterable)} instead. (Or, change {@code elements} to be a {@link
   * FluentIterable} and call {@code elements.toList()}.)
   *
   *
Performance note: {@link ArrayList} and {@link java.util.ArrayDeque} consistently
   * outperform {@code LinkedList} except in certain rare and specific situations. Unless you have
   * spent a lot of time benchmarking your specific needs, use one of those instead.
   *
   *
Note for Java 7 and later: if {@code elements} is a {@link Collection}, you don't
   * need this method. Use the {@code LinkedList} {@linkplain LinkedList#LinkedList(Collection)
   * constructor} directly, taking advantage of the new "diamond"
   * syntax.
   */
  @GwtCompatible(serializable = true)
  public static <E> LinkedList<E> newLinkedList(Iterable<? extends E> elements) {
    LinkedList<E> list = newLinkedList();
    Iterables.addAll(list, elements);
    return list;
  }

  /**
   * Creates an empty {@code CopyOnWriteArrayList} instance.
   *
   *
Note: if you need an immutable empty {@link List}, use {@link Collections#emptyList}
   * instead.
   *
   * @return a new, empty {@code CopyOnWriteArrayList}
   * @since 12.0
   */
  @GwtIncompatible // CopyOnWriteArrayList
  public static <E> CopyOnWriteArrayList<E> newCopyOnWriteArrayList() {
    return new CopyOnWriteArrayList<>();
  }

  /**
   * Creates a {@code CopyOnWriteArrayList} instance containing the given elements.
   *
   * @param elements the elements that the list should contain, in order
   * @return a new {@code CopyOnWriteArrayList} containing those elements
   * @since 12.0
   */
  @GwtIncompatible // CopyOnWriteArrayList
  public static <E> CopyOnWriteArrayList<E> newCopyOnWriteArrayList(
      Iterable<? extends E> elements) {
    // We copy elements to an ArrayList first, rather than incurring the
    // quadratic cost of adding them to the COWAL directly.
    Collection<? extends E> elementsCollection =
        (elements instanceof Collection) ? Collections2.cast(elements) : newArrayList(elements);
    return new CopyOnWriteArrayList<>(elementsCollection);
  }

  /**
   * Returns an unmodifiable list containing the specified first element and backed by the specified
   * array of additional elements. Changes to the {@code rest} array will be reflected in the
   * returned list. Unlike {@link Arrays#asList}, the returned list is unmodifiable.
   *
   *
This is useful when a varargs method needs to use a signature such as {@code (Foo firstFoo,
   * Foo... moreFoos)}, in order to avoid overload ambiguity or to enforce a minimum argument count.
   *
   *
The returned list is serializable and implements {@link RandomAccess}.
   *
   * @param first the first element
   * @param rest an array of additional elements, possibly empty
   * @return an unmodifiable list containing the specified elements
   */
  public static <E> List<E> asList(@Nullable E first, E[] rest) {
    return new OnePlusArrayList<>(first, rest);
  }

  /**
   * Returns an unmodifiable list containing the specified first and second element, and backed by
   * the specified array of additional elements. Changes to the {@code rest} array will be reflected
   * in the returned list. Unlike {@link Arrays#asList}, the returned list is unmodifiable.
   *
   *
This is useful when a varargs method needs to use a signature such as {@code (Foo firstFoo,
   * Foo secondFoo, Foo... moreFoos)}, in order to avoid overload ambiguity or to enforce a minimum
   * argument count.
   *
   *
The returned list is serializable and implements {@link RandomAccess}.
   *
   * @param first the first element
   * @param second the second element
   * @param rest an array of additional elements, possibly empty
   * @return an unmodifiable list containing the specified elements
   */
  public static <E> List<E> asList(@Nullable E first, @Nullable E second, E[] rest) {
    return new TwoPlusArrayList<>(first, second, rest);
  }

  /** @see Lists#asList(Object, Object[]) */
  private static class OnePlusArrayList<E> extends AbstractList<E>
      implements Serializable, RandomAccess {
    final @Nullable E first;
    final E[] rest;

    OnePlusArrayList(@Nullable E first, E[] rest) {
      this.first = first;
      this.rest = checkNotNull(rest);
    }

    @Override
    public int size() {
      return IntMath.saturatedAdd(rest.length, 1);
    }

    @Override
    public E get(int index) {
      // check explicitly so the IOOBE will have the right message
      checkElementIndex(index, size());
      return (index == 0) ? first : rest[index - 1];
    }

    private static final long serialVersionUID = 0;
  }

  /** @see Lists#asList(Object, Object, Object[]) */
  private static class TwoPlusArrayList<E> extends AbstractList<E>
      implements Serializable, RandomAccess {
    final @Nullable E first;
    final @Nullable E second;
    final E[] rest;

    TwoPlusArrayList(@Nullable E first, @Nullable E second, E[] rest) {
      this.first = first;
      this.second = second;
      this.rest = checkNotNull(rest);
    }

    @Override
    public int size() {
      return IntMath.saturatedAdd(rest.length, 2);
    }

    @Override
    public E get(int index) {
      switch (index) {
        case 0:
          return first;
        case 1:
          return second;
        default:
          // check explicitly so the IOOBE will have the right message
          checkElementIndex(index, size());
          return rest[index - 2];
      }
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * Returns every possible list that can be formed by choosing one element from each of the given
   * lists in order; the "n-ary Cartesian
   * product" of the lists. For example:
   *
   *
{@code
   * Lists.cartesianProduct(ImmutableList.of(
   *     ImmutableList.of(1, 2),
   *     ImmutableList.of("A", "B", "C")))
   * }

   *
   *
returns a list containing six lists in the following order:
   *
   *

   *
{@code ImmutableList.of(1, "A")}
   *
{@code ImmutableList.of(1, "B")}
   *
{@code ImmutableList.of(1, "C")}
   *
{@code ImmutableList.of(2, "A")}
   *
{@code ImmutableList.of(2, "B")}
   *
{@code ImmutableList.of(2, "C")}
   *

   *
   *
The result is guaranteed to be in the "traditional", lexicographical order for Cartesian
   * products that you would get from nesting for loops:
   *
   *
{@code
   * for (B b0 : lists.get(0)) {
   *   for (B b1 : lists.get(1)) {
   *     ...
   *     ImmutableList tuple = ImmutableList.of(b0, b1, ...);
   *     // operate on tuple
   *   }
   * }
   * }

   *
   *
Note that if any input list is empty, the Cartesian product will also be empty. If no lists
   * at all are provided (an empty list), the resulting Cartesian product has one element, an empty
   * list (counter-intuitive, but mathematically consistent).
   *
   *
Performance notes: while the cartesian product of lists of size {@code m, n, p} is a
   * list of size {@code m x n x p}, its actual memory consumption is much smaller. When the
   * cartesian product is constructed, the input lists are merely copied. Only as the resulting list
   * is iterated are the individual lists created, and these are not retained after iteration.
   *
   * @param lists the lists to choose elements from, in the order that the elements chosen from
   *     those lists should appear in the resulting lists
   * @param  any common base class shared by all axes (often just {@link Object})
   * @return the Cartesian product, as an immutable list containing immutable lists
   * @throws IllegalArgumentException if the size of the cartesian product would be greater than
   *     {@link Integer#MAX_VALUE}
   * @throws NullPointerException if {@code lists}, any one of the {@code lists}, or any element of
   *     a provided list is null
   * @since 19.0
   */
  public static  List<List> cartesianProduct(List<? extends List<? extends B>> lists) {
    return CartesianList.create(lists);
  }

  /**
   * Returns every possible list that can be formed by choosing one element from each of the given
   * lists in order; the "n-ary Cartesian
   * product" of the lists. For example:
   *
   *
{@code
   * Lists.cartesianProduct(ImmutableList.of(
   *     ImmutableList.of(1, 2),
   *     ImmutableList.of("A", "B", "C")))
   * }

   *
   *
returns a list containing six lists in the following order:
   *
   *

   *
{@code ImmutableList.of(1, "A")}
   *
{@code ImmutableList.of(1, "B")}
   *
{@code ImmutableList.of(1, "C")}
   *
{@code ImmutableList.of(2, "A")}
   *
{@code ImmutableList.of(2, "B")}
   *
{@code ImmutableList.of(2, "C")}
   *

   *
   *
The result is guaranteed to be in the "traditional", lexicographical order for Cartesian
   * products that you would get from nesting for loops:
   *
   *
{@code
   * for (B b0 : lists.get(0)) {
   *   for (B b1 : lists.get(1)) {
   *     ...
   *     ImmutableList tuple = ImmutableList.of(b0, b1, ...);
   *     // operate on tuple
   *   }
   * }
   * }

   *
   *
Note that if any input list is empty, the Cartesian product will also be empty. If no lists
   * at all are provided (an empty list), the resulting Cartesian product has one element, an empty
   * list (counter-intuitive, but mathematically consistent).
   *
   *
Performance notes: while the cartesian product of lists of size {@code m, n, p} is a
   * list of size {@code m x n x p}, its actual memory consumption is much smaller. When the
   * cartesian product is constructed, the input lists are merely copied. Only as the resulting list
   * is iterated are the individual lists created, and these are not retained after iteration.
   *
   * @param lists the lists to choose elements from, in the order that the elements chosen from
   *     those lists should appear in the resulting lists
   * @param  any common base class shared by all axes (often just {@link Object})
   * @return the Cartesian product, as an immutable list containing immutable lists
   * @throws IllegalArgumentException if the size of the cartesian product would be greater than
   *     {@link Integer#MAX_VALUE}
   * @throws NullPointerException if {@code lists}, any one of the {@code lists}, or any element of
   *     a provided list is null
   * @since 19.0
   */
  @SafeVarargs
  public static  List<List> cartesianProduct(List<? extends B>... lists) {
    return cartesianProduct(Arrays.asList(lists));
  }

  /**
   * Returns a list that applies {@code function} to each element of {@code fromList}. The returned
   * list is a transformed view of {@code fromList}; changes to {@code fromList} will be reflected
   * in the returned list and vice versa.
   *
   *
Since functions are not reversible, the transform is one-way and new items cannot be stored
   * in the returned list. The {@code add}, {@code addAll} and {@code set} methods are unsupported
   * in the returned list.
   *
   *
The function is applied lazily, invoked when needed. This is necessary for the returned list
   * to be a view, but it means that the function will be applied many times for bulk operations
   * like {@link List#contains} and {@link List#hashCode}. For this to perform well, {@code
   * function} should be fast. To avoid lazy evaluation when the returned list doesn't need to be a
   * view, copy the returned list into a new list of your choosing.
   *
   *
If {@code fromList} implements {@link RandomAccess}, so will the returned list. The returned
   * list is threadsafe if the supplied list and function are.
   *
   *
If only a {@code Collection} or {@code Iterable} input is available, use {@link
   * Collections2#transform} or {@link Iterables#transform}.
   *
   *
Note: serializing the returned list is implemented by serializing {@code fromList},
   * its contents, and {@code function} -- not by serializing the transformed values. This
   * can lead to surprising behavior, so serializing the returned list is not recommended.
   * Instead, copy the list using {@link ImmutableList#copyOf(Collection)} (for example), then
   * serialize the copy. Other methods similar to this do not implement serialization at all for
   * this reason.
   *
   *
Java 8 users: many use cases for this method are better addressed by {@link
   * java.util.stream.Stream#map}. This method is not being deprecated, but we gently encourage you
   * to migrate to streams.
   */
  public static <F, T> List<T> transform(
      List<F> fromList, Function<? super F, ? extends T> function) {
    return (fromList instanceof RandomAccess)
        ? new TransformingRandomAccessList<>(fromList, function)
        : new TransformingSequentialList<>(fromList, function);
  }

  /**
   * Implementation of a sequential transforming list.
   *
   * @see Lists#transform
   */
  private static class TransformingSequentialList<F, T> extends AbstractSequentialList<T>
      implements Serializable {
    final List<F> fromList;
    final Function<? super F, ? extends T> function;

    TransformingSequentialList(List<F> fromList, Function<? super F, ? extends T> function) {
      this.fromList = checkNotNull(fromList);
      this.function = checkNotNull(function);
    }

    /**
     * The default implementation inherited is based on iteration and removal of each element which
     * can be overkill. That's why we forward this call directly to the backing list.
     */
    @Override
    public void clear() {
      fromList.clear();
    }

    @Override
    public int size() {
      return fromList.size();
    }

    @Override
    public ListIterator<T> listIterator(final int index) {
      return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
        @Override
        T transform(F from) {
          return function.apply(from);
        }
      };
    }

    @Override
    public boolean removeIf(Predicate<? super T> filter) {
      checkNotNull(filter);
      return fromList.removeIf(element -> filter.test(function.apply(element)));
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * Implementation of a transforming random access list. We try to make as many of these methods
   * pass-through to the source list as possible so that the performance characteristics of the
   * source list and transformed list are similar.
   *
   * @see Lists#transform
   */
  private static class TransformingRandomAccessList<F, T> extends AbstractList<T>
      implements RandomAccess, Serializable {
    final List<F> fromList;
    final Function<? super F, ? extends T> function;

    TransformingRandomAccessList(List<F> fromList, Function<? super F, ? extends T> function) {
      this.fromList = checkNotNull(fromList);
      this.function = checkNotNull(function);
    }

    @Override
    public void clear() {
      fromList.clear();
    }

    @Override
    public T get(int index) {
      return function.apply(fromList.get(index));
    }

    @Override
    public Iterator<T> iterator() {
      return listIterator();
    }

    @Override
    public ListIterator<T> listIterator(int index) {
      return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
        @Override
        T transform(F from) {
          return function.apply(from);
        }
      };
    }

    @Override
    public boolean isEmpty() {
      return fromList.isEmpty();
    }

    @Override
    public boolean removeIf(Predicate<? super T> filter) {
      checkNotNull(filter);
      return fromList.removeIf(element -> filter.test(function.apply(element)));
    }

    @Override
    public T remove(int index) {
      return function.apply(fromList.remove(index));
    }

    @Override
    public int size() {
      return fromList.size();
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * Returns consecutive {@linkplain List#subList(int, int) sublists} of a list, each of the same
   * size (the final list may be smaller). For example, partitioning a list containing {@code [a, b,
   * c, d, e]} with a partition size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list
   * containing two inner lists of three and two elements, all in the original order.
   *
   *
The outer list is unmodifiable, but reflects the latest state of the source list. The inner
   * lists are sublist views of the original list, produced on demand using {@link List#subList(int,
   * int)}, and are subject to all the usual caveats about modification as explained in that API.
   *
   * @param list the list to return consecutive sublists of
   * @param size the desired size of each sublist (the last may be smaller)
   * @return a list of consecutive sublists
   * @throws IllegalArgumentException if {@code partitionSize} is nonpositive
   */
  public static <T> List<List<T>> partition(List<T> list, int size) {
    checkNotNull(list);
    checkArgument(size > 0);
    return (list instanceof RandomAccess)
        ? new RandomAccessPartition<>(list, size)
        : new Partition<>(list, size);
  }

  private static class Partition<T> extends AbstractList<List<T>> {
    final List<T> list;
    final int size;

    Partition(List<T> list, int size) {
      this.list = list;
      this.size = size;
    }

    @Override
    public List<T> get(int index) {
      checkElementIndex(index, size());
      int start = index * size;
      int end = Math.min(start + size, list.size());
      return list.subList(start, end);
    }

    @Override
    public int size() {
      return IntMath.divide(list.size(), size, RoundingMode.CEILING);
    }

    @Override
    public boolean isEmpty() {
      return list.isEmpty();
    }
  }

  private static class RandomAccessPartition<T> extends Partition<T> implements RandomAccess {
    RandomAccessPartition(List<T> list, int size) {
      super(list, size);
    }
  }

  /**
   * Returns a view of the specified string as an immutable list of {@code Character} values.
   *
   * @since 7.0
   */
  public static ImmutableList<Character> charactersOf(String string) {
    return new StringAsImmutableList(checkNotNull(string));
  }

  /**
   * Returns a view of the specified {@code CharSequence} as a {@code List<Character>}, viewing
   * {@code sequence} as a sequence of Unicode code units. The view does not support any
   * modification operations, but reflects any changes to the underlying character sequence.
   *
   * @param sequence the character sequence to view as a {@code List} of characters
   * @return an {@code List<Character>} view of the character sequence
   * @since 7.0
   */
  @Beta
  public static List<Character> charactersOf(CharSequence sequence) {
    return new CharSequenceAsList(checkNotNull(sequence));
  }

  @SuppressWarnings("serial") // serialized using ImmutableList serialization
  private static final class StringAsImmutableList extends ImmutableList<Character> {

    private final String string;

    StringAsImmutableList(String string) {
      this.string = string;
    }

    @Override
    public int indexOf(@Nullable Object object) {
      return (object instanceof Character) ? string.indexOf((Character) object) : -1;
    }

    @Override
    public int lastIndexOf(@Nullable Object object) {
      return (object instanceof Character) ? string.lastIndexOf((Character) object) : -1;
    }

    @Override
    public ImmutableList<Character> subList(int fromIndex, int toIndex) {
      checkPositionIndexes(fromIndex, toIndex, size()); // for GWT
      return charactersOf(string.substring(fromIndex, toIndex));
    }

    @Override
    boolean isPartialView() {
      return false;
    }

    @Override
    public Character get(int index) {
      checkElementIndex(index, size()); // for GWT
      return string.charAt(index);
    }

    @Override
    public int size() {
      return string.length();
    }
  }

  private static final class CharSequenceAsList extends AbstractList<Character> {
    private final CharSequence sequence;

    CharSequenceAsList(CharSequence sequence) {
      this.sequence = sequence;
    }

    @Override
    public Character get(int index) {
      checkElementIndex(index, size()); // for GWT
      return sequence.charAt(index);
    }

    @Override
    public int size() {
      return sequence.length();
    }
  }

  /**
   * Returns a reversed view of the specified list. For example, {@code
   * Lists.reverse(Arrays.asList(1, 2, 3))} returns a list containing {@code 3, 2, 1}. The returned
   * list is backed by this list, so changes in the returned list are reflected in this list, and
   * vice-versa. The returned list supports all of the optional list operations supported by this
   * list.
   *
   *
The returned list is random-access if the specified list is random access.
   *
   * @since 7.0
   */
  public static <T> List<T> reverse(List<T> list) {
    if (list instanceof ImmutableList) {
      return ((ImmutableList<T>) list).reverse();
    } else if (list instanceof ReverseList) {
      return ((ReverseList<T>) list).getForwardList();
    } else if (list instanceof RandomAccess) {
      return new RandomAccessReverseList<>(list);
    } else {
      return new ReverseList<>(list);
    }
  }

  private static class ReverseList<T> extends AbstractList<T> {
    private final List<T> forwardList;

    ReverseList(List<T> forwardList) {
      this.forwardList = checkNotNull(forwardList);
    }

    List<T> getForwardList() {
      return forwardList;
    }

    private int reverseIndex(int index) {
      int size = size();
      checkElementIndex(index, size);
      return (size - 1) - index;
    }

    private int reversePosition(int index) {
      int size = size();
      checkPositionIndex(index, size);
      return size - index;
    }

    @Override
    public void add(int index, @Nullable T element) {
      forwardList.add(reversePosition(index), element);
    }

    @Override
    public void clear() {
      forwardList.clear();
    }

    @Override
    public T remove(int index) {
      return forwardList.remove(reverseIndex(index));
    }

    @Override
    protected void removeRange(int fromIndex, int toIndex) {
      subList(fromIndex, toIndex).clear();
    }

    @Override
    public T set(int index, @Nullable T element) {
      return forwardList.set(reverseIndex(index), element);
    }

    @Override
    public T get(int index) {
      return forwardList.get(reverseIndex(index));
    }

    @Override
    public int size() {
      return forwardList.size();
    }

    @Override
    public List<T> subList(int fromIndex, int toIndex) {
      checkPositionIndexes(fromIndex, toIndex, size());
      return reverse(forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)));
    }

    @Override
    public Iterator<T> iterator() {
      return listIterator();
    }

    @Override
    public ListIterator<T> listIterator(int index) {
      int start = reversePosition(index);
      final ListIterator<T> forwardIterator = forwardList.listIterator(start);
      return new ListIterator<T>() {

        boolean canRemoveOrSet;

        @Override
        public void add(T e) {
          forwardIterator.add(e);
          forwardIterator.previous();
          canRemoveOrSet = false;
        }

        @Override
        public boolean hasNext() {
          return forwardIterator.hasPrevious();
        }

        @Override
        public boolean hasPrevious() {
          return forwardIterator.hasNext();
        }

        @Override
        public T next() {
          if (!hasNext()) {
            throw new NoSuchElementException();
          }
          canRemoveOrSet = true;
          return forwardIterator.previous();
        }

        @Override
        public int nextIndex() {
          return reversePosition(forwardIterator.nextIndex());
        }

        @Override
        public T previous() {
          if (!hasPrevious()) {
            throw new NoSuchElementException();
          }
          canRemoveOrSet = true;
          return forwardIterator.next();
        }

        @Override
        public int previousIndex() {
          return nextIndex() - 1;
        }

        @Override
        public void remove() {
          checkRemove(canRemoveOrSet);
          forwardIterator.remove();
          canRemoveOrSet = false;
        }

        @Override
        public void set(T e) {
          checkState(canRemoveOrSet);
          forwardIterator.set(e);
        }
      };
    }
  }

  private static class RandomAccessReverseList<T> extends ReverseList<T> implements RandomAccess {
    RandomAccessReverseList(List<T> forwardList) {
      super(forwardList);
    }
  }

  /** An implementation of {@link List#hashCode()}. */
  static int hashCodeImpl(List<?> list) {
    // TODO(lowasser): worth optimizing for RandomAccess?
    int hashCode = 1;
    for (Object o : list) {
      hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());

      hashCode = ~~hashCode;
      // needed to deal with GWT integer overflow
    }
    return hashCode;
  }

  /** An implementation of {@link List#equals(Object)}. */
  static boolean equalsImpl(List<?> thisList, @Nullable Object other) {
    if (other == checkNotNull(thisList)) {
      return true;
    }
    if (!(other instanceof List)) {
      return false;
    }
    List<?> otherList = (List<?>) other;
    int size = thisList.size();
    if (size != otherList.size()) {
      return false;
    }
    if (thisList instanceof RandomAccess && otherList instanceof RandomAccess) {
      // avoid allocation and use the faster loop
      for (int i = 0; i < size; i++) {
        if (!Objects.equal(thisList.get(i), otherList.get(i))) {
          return false;
        }
      }
      return true;
    } else {
      return Iterators.elementsEqual(thisList.iterator(), otherList.iterator());
    }
  }

  /** An implementation of {@link List#addAll(int, Collection)}. */
  static <E> boolean addAllImpl(List<E> list, int index, Iterable<? extends E> elements) {
    boolean changed = false;
    ListIterator<E> listIterator = list.listIterator(index);
    for (E e : elements) {
      listIterator.add(e);
      changed = true;
    }
    return changed;
  }

  /** An implementation of {@link List#indexOf(Object)}. */
  static int indexOfImpl(List<?> list, @Nullable Object element) {
    if (list instanceof RandomAccess) {
      return indexOfRandomAccess(list, element);
    } else {
      ListIterator<?> listIterator = list.listIterator();
      while (listIterator.hasNext()) {
        if (Objects.equal(element, listIterator.next())) {
          return listIterator.previousIndex();
        }
      }
      return -1;
    }
  }

  private static int indexOfRandomAccess(List<?> list, @Nullable Object element) {
    int size = list.size();
    if (element == null) {
      for (int i = 0; i < size; i++) {
        if (list.get(i) == null) {
          return i;
        }
      }
    } else {
      for (int i = 0; i < size; i++) {
        if (element.equals(list.get(i))) {
          return i;
        }
      }
    }
    return -1;
  }

  /** An implementation of {@link List#lastIndexOf(Object)}. */
  static int lastIndexOfImpl(List<?> list, @Nullable Object element) {
    if (list instanceof RandomAccess) {
      return lastIndexOfRandomAccess(list, element);
    } else {
      ListIterator<?> listIterator = list.listIterator(list.size());
      while (listIterator.hasPrevious()) {
        if (Objects.equal(element, listIterator.previous())) {
          return listIterator.nextIndex();
        }
      }
      return -1;
    }
  }

  private static int lastIndexOfRandomAccess(List<?> list, @Nullable Object element) {
    if (element == null) {
      for (int i = list.size() - 1; i >= 0; i--) {
        if (list.get(i) == null) {
          return i;
        }
      }
    } else {
      for (int i = list.size() - 1; i >= 0; i--) {
        if (element.equals(list.get(i))) {
          return i;
        }
      }
    }
    return -1;
  }

  /** Returns an implementation of {@link List#listIterator(int)}. */
  static <E> ListIterator<E> listIteratorImpl(List<E> list, int index) {
    return new AbstractListWrapper<>(list).listIterator(index);
  }

  /** An implementation of {@link List#subList(int, int)}. */
  static <E> List<E> subListImpl(final List<E> list, int fromIndex, int toIndex) {
    List<E> wrapper;
    if (list instanceof RandomAccess) {
      wrapper =
          new RandomAccessListWrapper<E>(list) {
            @Override
            public ListIterator<E> listIterator(int index) {
              return backingList.listIterator(index);
            }

            private static final long serialVersionUID = 0;
          };
    } else {
      wrapper =
          new AbstractListWrapper<E>(list) {
            @Override
            public ListIterator<E> listIterator(int index) {
              return backingList.listIterator(index);
            }

            private static final long serialVersionUID = 0;
          };
    }
    return wrapper.subList(fromIndex, toIndex);
  }

  private static class AbstractListWrapper<E> extends AbstractList<E> {
    final List<E> backingList;

    AbstractListWrapper(List<E> backingList) {
      this.backingList = checkNotNull(backingList);
    }

    @Override
    public void add(int index, E element) {
      backingList.add(index, element);
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
      return backingList.addAll(index, c);
    }

    @Override
    public E get(int index) {
      return backingList.get(index);
    }

    @Override
    public E remove(int index) {
      return backingList.remove(index);
    }

    @Override
    public E set(int index, E element) {
      return backingList.set(index, element);
    }

    @Override
    public boolean contains(Object o) {
      return backingList.contains(o);
    }

    @Override
    public int size() {
      return backingList.size();
    }
  }

  private static class RandomAccessListWrapper<E> extends AbstractListWrapper<E>
      implements RandomAccess {
    RandomAccessListWrapper(List<E> backingList) {
      super(backingList);
    }
  }

  /** Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557 */
  static <T> List<T> cast(Iterable<T> iterable) {
    return (List<T>) iterable;
  }
}


/*
 * Copyright (C) 2009 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.collect;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import java.util.Comparator;
import java.util.Spliterator;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * List returned by {@code ImmutableSortedSet.asList()} when the set isn't empty.
 *
 * @author Jared Levy
 * @author Louis Wasserman
 */
@GwtCompatible(emulated = true)
@SuppressWarnings("serial")
final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
    implements SortedIterable<E> {
  ImmutableSortedAsList(ImmutableSortedSet<E> backingSet, ImmutableList<E> backingList) {
    super(backingSet, backingList);
  }

  @Override
  ImmutableSortedSet<E> delegateCollection() {
    return (ImmutableSortedSet<E>) super.delegateCollection();
  }

  @Override
  public Comparator<? super E> comparator() {
    return delegateCollection().comparator();
  }

  // Override indexOf() and lastIndexOf() to be O(log N) instead of O(N).

  @GwtIncompatible // ImmutableSortedSet.indexOf
  // TODO(cpovirk): consider manual binary search under GWT to preserve O(log N) lookup
  @Override
  public int indexOf(@Nullable Object target) {
    int index = delegateCollection().indexOf(target);

    // TODO(kevinb): reconsider if it's really worth making feeble attempts at
    // sanity for inconsistent comparators.

    // The equals() check is needed when the comparator isn't compatible with
    // equals().
    return (index >= 0 && get(index).equals(target)) ? index : -1;
  }

  @GwtIncompatible // ImmutableSortedSet.indexOf
  @Override
  public int lastIndexOf(@Nullable Object target) {
    return indexOf(target);
  }

  @Override
  public boolean contains(Object target) {
    // Necessary for ISS's with comparators inconsistent with equals.
    return indexOf(target) >= 0;
  }

  @GwtIncompatible // super.subListUnchecked does not exist; inherited subList is valid if slow
  /*
   * TODO(cpovirk): if we start to override indexOf/lastIndexOf under GWT, we'll want some way to
   * override subList to return an ImmutableSortedAsList for better performance. Right now, I'm not
   * sure there's any performance hit from our failure to override subListUnchecked under GWT
   */
  @Override
  ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) {
    ImmutableList<E> parentSubList = super.subListUnchecked(fromIndex, toIndex);
    return new RegularImmutableSortedSet<E>(parentSubList, comparator()).asList();
  }

  @Override
  public Spliterator<E> spliterator() {
    return CollectSpliterators.indexed(
        size(),
        ImmutableList.SPLITERATOR_CHARACTERISTICS | Spliterator.SORTED | Spliterator.DISTINCT,
        delegateList()::get,
        comparator());
  }
}


/*
 * Copyright (C) 2008 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.common.base;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.GwtCompatible;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.ForOverride;
import com.google.errorprone.annotations.concurrent.LazyInit;
import java.io.Serializable;
import java.util.Iterator;
import org.checkerframework.checker.nullness.compatqual.MonotonicNonNullDecl;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

/**
 * A function from {@code A} to {@code B} with an associated reverse function from {@code B}
 * to {@code A}; used for converting back and forth between different representations of the same
 * information.
 *
 *
Invertibility

 *
 *
The reverse operation may be a strict inverse (meaning that {@code
 * converter.reverse().convert(converter.convert(a)).equals(a)} is always true). However, it is very
 * common (perhaps more common) for round-trip conversion to be lossy. Consider an
 * example round-trip using {@link com.google.common.primitives.Doubles#stringConverter}:
 *
 *

 *
{@code stringConverter().convert("1.00")} returns the {@code Double} value {@code 1.0}
 *
{@code stringConverter().reverse().convert(1.0)} returns the string {@code "1.0"} --
 *       not the same string ({@code "1.00"}) we started with
 *

 *
 *
Note that it should still be the case that the round-tripped and original objects are
 * similar.
 *
 *
Nullability

 *
 *
A converter always converts {@code null} to {@code null} and non-null references to non-null
 * references. It would not make sense to consider {@code null} and a non-null reference to be
 * "different representations of the same information", since one is distinguishable from
 * missing information and the other is not. The {@link #convert} method handles this null
 * behavior for all converters; implementations of {@link #doForward} and {@link #doBackward} are
 * guaranteed to never be passed {@code null}, and must never return {@code null}.
 *
 *
 *
Common ways to use

 *
 *
Getting a converter:
 *
 *

 *
Use a provided converter implementation, such as {@link Enums#stringConverter}, {@link
 *       com.google.common.primitives.Ints#stringConverter Ints.stringConverter} or the {@linkplain
 *       #reverse reverse} views of these.
 *
Convert between specific preset values using {@link
 *       com.google.common.collect.Maps#asConverter Maps.asConverter}. For example, use this to
 *       create a "fake" converter for a unit test. It is unnecessary (and confusing) to mock
 *       the {@code Converter} type using a mocking framework.
 *
Extend this class and implement its {@link #doForward} and {@link #doBackward} methods.
 *
Java 8 users: you may prefer to pass two lambda expressions or method references to
 *       the {@link #from from} factory method.
 *

 *
 *
Using a converter:
 *
 *

 *
Convert one instance in the "forward" direction using {@code converter.convert(a)}.
 *
Convert multiple instances "forward" using {@code converter.convertAll(as)}.
 *
Convert in the "backward" direction using {@code converter.reverse().convert(b)} or {@code
 *       converter.reverse().convertAll(bs)}.
 *
Use {@code converter} or {@code converter.reverse()} anywhere a {@link
 *       java.util.function.Function} is accepted (for example {@link java.util.stream.Stream#map
 *       Stream.map}).
 *
Do not call {@link #doForward} or {@link #doBackward} directly; these exist only to
 *       be overridden.
 *

 *
 *
Example

 *
 *

 *   return new Converter<Integer, String>() {
 *     protected String doForward(Integer i) {
 *       return Integer.toHexString(i);
 *     }
 *
 *     protected Integer doBackward(String s) {
 *       return parseUnsignedInt(s, 16);
 *     }
 *   };

 *
 *
An alternative using Java 8:
 *
 *
{@code
 * return Converter.from(
 *     Integer::toHexString,
 *     s -> parseUnsignedInt(s, 16));
 * }

 *
 * @author Mike Ward
 * @author Kurt Alfred Kluever
 * @author Gregory Kick
 * @since 16.0
 */
@GwtCompatible
public abstract class Converter implements Function {
  private final boolean handleNullAutomatically;

  // We lazily cache the reverse view to avoid allocating on every call to reverse().
  @LazyInit @MonotonicNonNullDecl private transient Converter reverse;

  /** Constructor for use by subclasses. */
  protected Converter() {
    this(true);
  }

  /** Constructor used only by {@code LegacyConverter} to suspend automatic null-handling. */
  Converter(boolean handleNullAutomatically) {
    this.handleNullAutomatically = handleNullAutomatically;
  }

  // SPI methods (what subclasses must implement)

  /**
   * Returns a representation of {@code a} as an instance of type {@code B}. If {@code a} cannot be
   * converted, an unchecked exception (such as {@link IllegalArgumentException}) should be thrown.
   *
   * @param a the instance to convert; will never be null
   * @return the converted instance; must not be null
   */
  @ForOverride
  protected abstract B doForward(A a);

  /**
   * Returns a representation of {@code b} as an instance of type {@code A}. If {@code b} cannot be
   * converted, an unchecked exception (such as {@link IllegalArgumentException}) should be thrown.
   *
   * @param b the instance to convert; will never be null
   * @return the converted instance; must not be null
   * @throws UnsupportedOperationException if backward conversion is not implemented; this should be
   *     very rare. Note that if backward conversion is not only unimplemented but
   *     unimplementable (for example, consider a {@code Converter<Chicken, ChickenNugget>}),
   *     then this is not logically a {@code Converter} at all, and should just implement {@link
   *     Function}.
   */
  @ForOverride
  protected abstract A doBackward(B b);

  // API (consumer-side) methods

  /**
   * Returns a representation of {@code a} as an instance of type {@code B}.
   *
   * @return the converted value; is null if and only if {@code a} is null
   */
  @CanIgnoreReturnValue
  @NullableDecl
  public final B convert(@NullableDecl A a) {
    return correctedDoForward(a);
  }

  @NullableDecl
  B correctedDoForward(@NullableDecl A a) {
    if (handleNullAutomatically) {
      // TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
      return a == null ? null : checkNotNull(doForward(a));
    } else {
      return doForward(a);
    }
  }

  @NullableDecl
  A correctedDoBackward(@NullableDecl B b) {
    if (handleNullAutomatically) {
      // TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
      return b == null ? null : checkNotNull(doBackward(b));
    } else {
      return doBackward(b);
    }
  }

  /**
   * Returns an iterable that applies {@code convert} to each element of {@code fromIterable}. The
   * conversion is done lazily.
   *
   *
The returned iterable's iterator supports {@code remove()} if the input iterator does. After
   * a successful {@code remove()} call, {@code fromIterable} no longer contains the corresponding
   * element.
   */
  @CanIgnoreReturnValue
  public Iterable convertAll(final Iterable<? extends A> fromIterable) {
    checkNotNull(fromIterable, "fromIterable");
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          private final Iterator<? extends A> fromIterator = fromIterable.iterator();

          @Override
          public boolean hasNext() {
            return fromIterator.hasNext();
          }

          @Override
          public B next() {
            return convert(fromIterator.next());
          }

          @Override
          public void remove() {
            fromIterator.remove();
          }
        };
      }
    };
  }

  /**
   * Returns the reversed view of this converter, which converts {@code this.convert(a)} back to a
   * value roughly equivalent to {@code a}.
   *
   *
The returned converter is serializable if {@code this} converter is.
   *
   *
Note: you should not override this method. It is non-final for legacy reasons.
   */
  @CanIgnoreReturnValue
  public Converter reverse() {
    Converter result = reverse;
    return (result == null) ? reverse = new ReverseConverter<>(this) : result;
  }

  private static final class ReverseConverter extends Converter
      implements Serializable {
    final Converter original;

    ReverseConverter(Converter original) {
      this.original = original;
    }

    /*
     * These gymnastics are a little confusing. Basically this class has neither legacy nor
     * non-legacy behavior; it just needs to let the behavior of the backing converter shine
     * through. So, we override the correctedDo* methods, after which the do* methods should never
     * be reached.
     */

    @Override
    protected A doForward(B b) {
      throw new AssertionError();
    }

    @Override
    protected B doBackward(A a) {
      throw new AssertionError();
    }

    @Override
    @NullableDecl
    A correctedDoForward(@NullableDecl B b) {
      return original.correctedDoBackward(b);
    }

    @Override
    @NullableDecl
    B correctedDoBackward(@NullableDecl A a) {
      return original.correctedDoForward(a);
    }

    @Override
    public Converter reverse() {
      return original;
    }

    @Override
    public boolean equals(@NullableDecl Object object) {
      if (object instanceof ReverseConverter) {
        ReverseConverter<?, ?> that = (ReverseConverter<?, ?>) object;
        return this.original.equals(that.original);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return ~original.hashCode();
    }

    @Override
    public String toString() {
      return original + ".reverse()";
    }

    private static final long serialVersionUID = 0L;
  }

  /**
   * Returns a converter whose {@code convert} method applies {@code secondConverter} to the result
   * of this converter. Its {@code reverse} method applies the converters in reverse order.
   *
   *
The returned converter is serializable if {@code this} converter and {@code secondConverter}
   * are.
   */
  public final <C> Converter andThen(Converter secondConverter) {
    return doAndThen(secondConverter);
  }

  /** Package-private non-final implementation of andThen() so only we can override it. */
  <C> Converter doAndThen(Converter secondConverter) {
    return new ConverterComposition<>(this, checkNotNull(secondConverter));
  }

  private static final class ConverterComposition extends Converter
      implements Serializable {
    final Converter first;
    final Converter second;

    ConverterComposition(Converter first, Converter second) {
      this.first = first;
      this.second = second;
    }

    /*
     * These gymnastics are a little confusing. Basically this class has neither legacy nor
     * non-legacy behavior; it just needs to let the behaviors of the backing converters shine
     * through (which might even differ from each other!). So, we override the correctedDo* methods,
     * after which the do* methods should never be reached.
     */

    @Override
    protected C doForward(A a) {
      throw new AssertionError();
    }

    @Override
    protected A doBackward(C c) {
      throw new AssertionError();
    }

    @Override
    @NullableDecl
    C correctedDoForward(@NullableDecl A a) {
      return second.correctedDoForward(first.correctedDoForward(a));
    }

    @Override
    @NullableDecl
    A correctedDoBackward(@NullableDecl C c) {
      return first.correctedDoBackward(second.correctedDoBackward(c));
    }

    @Override
    public boolean equals(@NullableDecl Object object) {
      if (object instanceof ConverterComposition) {
        ConverterComposition<?, ?, ?> that = (ConverterComposition<?, ?, ?>) object;
        return this.first.equals(that.first) && this.second.equals(that.second);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return 31 * first.hashCode() + second.hashCode();
    }

    @Override
    public String toString() {
      return first + ".andThen(" + second + ")";
    }

    private static final long serialVersionUID = 0L;
  }

  /**
   * @deprecated Provided to satisfy the {@code Function} interface; use {@link #convert} instead.
   */
  @Deprecated
  @Override
  @CanIgnoreReturnValue
  @NullableDecl
  public final B apply(@NullableDecl A a) {
    return convert(a);
  }

  /**
   * Indicates whether another object is equal to this converter.
   *
   *
Most implementations will have no reason to override the behavior of {@link Object#equals}.
   * However, an implementation may also choose to return {@code true} whenever {@code object} is a
   * {@link Converter} that it considers interchangeable with this one. "Interchangeable"
   * typically means that {@code Objects.equal(this.convert(a), that.convert(a))} is true for
   * all {@code a} of type {@code A} (and similarly for {@code reverse}). Note that a {@code false}
   * result from this method does not imply that the converters are known not to be
   * interchangeable.
   */
  @Override
  public boolean equals(@NullableDecl Object object) {
    return super.equals(object);
  }

  // Static converters

  /**
   * Returns a converter based on separate forward and backward functions. This is useful if the
   * function instances already exist, or so that you can supply lambda expressions. If those
   * circumstances don't apply, you probably don't need to use this; subclass {@code Converter} and
   * implement its {@link #doForward} and {@link #doBackward} methods directly.
   *
   *
These functions will never be passed {@code null} and must not under any circumstances
   * return {@code null}. If a value cannot be converted, the function should throw an unchecked
   * exception (typically, but not necessarily, {@link IllegalArgumentException}).
   *
   *
The returned converter is serializable if both provided functions are.
   *
   * @since 17.0
   */
  public static  Converter from(
      Function<? super A, ? extends B> forwardFunction,
      Function<? super B, ? extends A> backwardFunction) {
    return new FunctionBasedConverter<>(forwardFunction, backwardFunction);
  }

  private static final class FunctionBasedConverter extends Converter
      implements Serializable {
    private final Function<? super A, ? extends B> forwardFunction;
    private final Function<? super B, ? extends A> backwardFunction;

    private FunctionBasedConverter(
        Function<? super A, ? extends B> forwardFunction,
        Function<? super B, ? extends A> backwardFunction) {
      this.forwardFunction = checkNotNull(forwardFunction);
      this.backwardFunction = checkNotNull(backwardFunction);
    }

    @Override
    protected B doForward(A a) {
      return forwardFunction.apply(a);
    }

    @Override
    protected A doBackward(B b) {
      return backwardFunction.apply(b);
    }

    @Override
    public boolean equals(@NullableDecl Object object) {
      if (object instanceof FunctionBasedConverter) {
        FunctionBasedConverter<?, ?> that = (FunctionBasedConverter<?, ?>) object;
        return this.forwardFunction.equals(that.forwardFunction)
            && this.backwardFunction.equals(that.backwardFunction);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return forwardFunction.hashCode() * 31 + backwardFunction.hashCode();
    }

    @Override
    public String toString() {
      return "Converter.from(" + forwardFunction + ", " + backwardFunction + ")";
    }
  }

  /** Returns a serializable converter that always converts or reverses an object to itself. */
  @SuppressWarnings("unchecked") // implementation is "fully variant"
  public static <T> Converter<T, T> identity() {
    return (IdentityConverter<T>) IdentityConverter.INSTANCE;
  }

  /**
   * A converter that always converts or reverses an object to itself. Note that T is now a
   * "pass-through type".
   */
  private static final class IdentityConverter<T> extends Converter<T, T> implements Serializable {
    static final IdentityConverter INSTANCE = new IdentityConverter();

    @Override
    protected T doForward(T t) {
      return t;
    }

    @Override
    protected T doBackward(T t) {
      return t;
    }

    @Override
    public IdentityConverter<T> reverse() {
      return this;
    }

    @Override
    <S> Converter<T, S> doAndThen(Converter<T, S> otherConverter) {
      return checkNotNull(otherConverter, "otherConverter");
    }

    /*
     * We *could* override convertAll() to return its input, but it's a rather pointless
     * optimization and opened up a weird type-safety problem.
     */

    @Override
    public String toString() {
      return "Converter.identity()";
    }

    private Object readResolve() {
      return INSTANCE;
    }

    private static final long serialVersionUID = 0L;
  }
}