/*
 * 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.collect;

import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;

/**
 * A {@link BiMap} whose contents will never change, with many other important properties detailed
 * at {@link ImmutableCollection}.
 *
 * @author Jared Levy
 * @since 2.0
 */
@GwtCompatible(serializable = true, emulated = true)
public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> {

  /** Returns the empty bimap. */
  // Casting to any type is safe because the set will never hold any elements.
  @SuppressWarnings("unchecked")
  public static <K, V> ImmutableBiMap<K, V> of() {
    return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY;
  }

  /** Returns an immutable bimap containing a single entry. */
  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
    checkEntryNotNull(k1, v1);
    return new RegularImmutableBiMap<>(new Object[] {k1, v1}, 1);
  }

  /**
   * Returns an immutable map containing the given entries, in order.
   *
   * @throws IllegalArgumentException if duplicate keys or values are added
   */
  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
    checkEntryNotNull(k1, v1);
    checkEntryNotNull(k2, v2);
    return new RegularImmutableBiMap<K, V>(new Object[] {k1, v1, k2, v2}, 2);
  }

  /**
   * Returns an immutable map containing the given entries, in order.
   *
   * @throws IllegalArgumentException if duplicate keys or values are added
   */
  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
    checkEntryNotNull(k1, v1);
    checkEntryNotNull(k2, v2);
    checkEntryNotNull(k3, v3);
    return new RegularImmutableBiMap<K, V>(new Object[] {k1, v1, k2, v2, k3, v3}, 3);
  }

  /**
   * Returns an immutable map containing the given entries, in order.
   *
   * @throws IllegalArgumentException if duplicate keys or values are added
   */
  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
    checkEntryNotNull(k1, v1);
    checkEntryNotNull(k2, v2);
    checkEntryNotNull(k3, v3);
    checkEntryNotNull(k4, v4);
    return new RegularImmutableBiMap<K, V>(new Object[] {k1, v1, k2, v2, k3, v3, k4, v4}, 4);
  }

  /**
   * Returns an immutable map containing the given entries, in order.
   *
   * @throws IllegalArgumentException if duplicate keys or values are added
   */
  public static <K, V> ImmutableBiMap<K, V> of(
      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
    checkEntryNotNull(k1, v1);
    checkEntryNotNull(k2, v2);
    checkEntryNotNull(k3, v3);
    checkEntryNotNull(k4, v4);
    checkEntryNotNull(k5, v5);
    return new RegularImmutableBiMap<K, V>(
        new Object[] {k1, v1, k2, v2, k3, v3, k4, v4, k5, v5}, 5);
  }

  // looking for of() with > 5 entries? Use the builder instead.

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

  /**
   * Returns a new builder, expecting the specified number of entries to be added.
   *
   *
If {@code expectedSize} is exactly the number of entries added to the builder before {@link
   * Builder#build} is called, the builder is likely to perform better than an unsized {@link
   * #builder()} would have.
   *
   *
It is not specified if any performance benefits apply if {@code expectedSize} is close to,
   * but not exactly, the number of entries added to the builder.
   *
   * @since 23.1
   */
  @Beta
  public static <K, V> Builder<K, V> builderWithExpectedSize(int expectedSize) {
    checkNonnegative(expectedSize, "expectedSize");
    return new Builder<>(expectedSize);
  }

  /**
   * A builder for creating immutable bimap instances, especially {@code public static final} bimaps
   * ("constant bimaps"). Example:
   *
   *
{@code
   * static final ImmutableBiMap<String, Integer> WORD_TO_INT =
   *     new ImmutableBiMap.Builder<String, Integer>()
   *         .put("one", 1)
   *         .put("two", 2)
   *         .put("three", 3)
   *         .build();
   * }

   *
   *
For small immutable bimaps, the {@code ImmutableBiMap.of()} methods are even more
   * convenient.
   *
   *
By default, a {@code Builder} will generate bimaps that iterate over entries in the order
   * they were inserted into the builder. For example, in the above example, {@code
   * WORD_TO_INT.entrySet()} is guaranteed to iterate over the entries in the order {@code "one"=1,
   * "two"=2, "three"=3}, and {@code keySet()} and {@code values()} respect the same order. If you
   * want a different order, consider using {@link #orderEntriesByValue(Comparator)}, which changes
   * this builder to sort entries by value.
   *
   *
Builder instances can be reused - it is safe to call {@link #build} multiple times to build
   * multiple bimaps in series. Each bimap is a superset of the bimaps created before it.
   *
   * @since 2.0
   */
  public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
    /**
     * Creates a new builder. The returned builder is equivalent to the builder generated by {@link
     * ImmutableBiMap#builder}.
     */
    public Builder() {
      super();
    }

    Builder(int size) {
      super(size);
    }

    /**
     * Associates {@code key} with {@code value} in the built bimap. Duplicate keys or values are
     * not allowed, and will cause {@link #build} to fail.
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<K, V> put(K key, V value) {
      super.put(key, value);
      return this;
    }

    /**
     * Adds the given {@code entry} to the bimap. Duplicate keys or values are not allowed, and will
     * cause {@link #build} to fail.
     *
     * @since 19.0
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
      super.put(entry);
      return this;
    }

    /**
     * Associates all of the given map's keys and values in the built bimap. Duplicate keys or
     * values are not allowed, and will cause {@link #build} to fail.
     *
     * @throws NullPointerException if any key or value in {@code map} is null
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
      super.putAll(map);
      return this;
    }

    /**
     * Adds all of the given entries to the built bimap. Duplicate keys or values are not allowed,
     * and will cause {@link #build} to fail.
     *
     * @throws NullPointerException if any key, value, or entry is null
     * @since 19.0
     */
    @CanIgnoreReturnValue
    @Beta
    @Override
    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
      super.putAll(entries);
      return this;
    }

    /**
     * Configures this {@code Builder} to order entries by value according to the specified
     * comparator.
     *
     *
The sort order is stable, that is, if two entries have values that compare as equivalent,
     * the entry that was inserted first will be first in the built map's iteration order.
     *
     * @throws IllegalStateException if this method was already called
     * @since 19.0
     */
    @CanIgnoreReturnValue
    @Beta
    @Override
    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
      super.orderEntriesByValue(valueComparator);
      return this;
    }

    /**
     * Returns a newly-created immutable bimap. The iteration order of the returned bimap is the
     * order in which entries were inserted into the builder, unless {@link #orderEntriesByValue}
     * was called, in which case entries are sorted by value.
     *
     * @throws IllegalArgumentException if duplicate keys or values were added
     */
    @Override
    public ImmutableBiMap<K, V> build() {
      if (size == 0) {
        return of();
      }
      sortEntries();
      entriesUsed = true;
      return new RegularImmutableBiMap<K, V>(alternatingKeysAndValues, size);
    }
  }

  /**
   * Returns an immutable bimap containing the same entries as {@code map}. If {@code map} somehow
   * contains entries with duplicate keys (for example, if it is a {@code SortedMap} whose
   * comparator is not consistent with equals), the results of this method are undefined.
   *
   *
The returned {@code BiMap} iterates over entries in the same order as the {@code entrySet}
   * of the original map.
   *
   *
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.
   *
   * @throws IllegalArgumentException if two keys have the same value or two values have the same
   *     key
   * @throws NullPointerException if any key or value in {@code map} is null
   */
  public static <K, V> ImmutableBiMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
    if (map instanceof ImmutableBiMap) {
      @SuppressWarnings("unchecked") // safe since map is not writable
      ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
      // TODO(lowasser): if we need to make a copy of a BiMap because the
      // forward map is a view, don't make a copy of the non-view delegate map
      if (!bimap.isPartialView()) {
        return bimap;
      }
    }
    return copyOf(map.entrySet());
  }

  /**
   * Returns an immutable bimap containing the given entries. The returned bimap iterates over
   * entries in the same order as the original iterable.
   *
   * @throws IllegalArgumentException if two keys have the same value or two values have the same
   *     key
   * @throws NullPointerException if any key, value, or entry is null
   * @since 19.0
   */
  @Beta
  public static <K, V> ImmutableBiMap<K, V> copyOf(
      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
    int estimatedSize =
        (entries instanceof Collection)
            ? ((Collection<?>) entries).size()
            : ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY;
    return new Builder<K, V>(estimatedSize).putAll(entries).build();
  }

  ImmutableBiMap() {}

  /**
   * {@inheritDoc}
   *
   *
The inverse of an {@code ImmutableBiMap} is another {@code ImmutableBiMap}.
   */
  @Override
  public abstract ImmutableBiMap<V, K> inverse();

  /**
   * Returns an immutable set of the values in this map, in the same order they appear in {@link
   * #entrySet}.
   */
  @Override
  public ImmutableSet<V> values() {
    return inverse().keySet();
  }

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

  /**
   * Guaranteed to throw an exception and leave the bimap unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @CanIgnoreReturnValue
  @Deprecated
  @Override
  public V forcePut(K key, V value) {
    throw new UnsupportedOperationException();
  }

  /**
   * Serialized type for all ImmutableBiMap instances. It captures the logical contents and they are
   * reconstructed using public factory methods. This ensures that the implementation types remain
   * as implementation details.
   *
   *
Since the bimap is immutable, ImmutableBiMap doesn't require special logic for keeping the
   * bimap and its inverse in sync during serialization, the way AbstractBiMap does.
   */
  private static class SerializedForm extends ImmutableMap.SerializedForm {
    SerializedForm(ImmutableBiMap<?, ?> bimap) {
      super(bimap);
    }

    @Override
    Object readResolve() {
      Builder<Object, Object> builder = new Builder<>();
      return createMap(builder);
    }

    private static final long serialVersionUID = 0;
  }

  @Override
  Object writeReplace() {
    return new SerializedForm(this);
  }
}


/*
 * 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.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * A comparator, with additional methods to support common operations. This is an "enriched" version
 * of {@code Comparator} for pre-Java-8 users, in the same sense that {@link FluentIterable} is an
 * enriched {@link Iterable} for pre-Java-8 users.
 *
 *
Three types of methods

 *
 * Like other fluent types, there are three types of methods present: methods for acquiring,
 * chaining, and using.
 *
 *
Acquiring

 *
 *
The common ways to get an instance of {@code Ordering} are:
 *
 *

 *
Subclass it and implement {@link #compare} instead of implementing {@link Comparator}
 *       directly
 *
Pass a pre-existing {@link Comparator} instance to {@link #from(Comparator)}
 *
Use the natural ordering, {@link Ordering#natural}
 *

 *
 *
Chaining

 *
 *
Then you can use the chaining methods to get an altered version of that {@code
 * Ordering}, including:
 *
 *

 *
{@link #reverse}
 *
{@link #compound(Comparator)}
 *
{@link #onResultOf(Function)}
 *
{@link #nullsFirst} / {@link #nullsLast}
 *

 *
 *
Using

 *
 *
Finally, use the resulting {@code Ordering} anywhere a {@link Comparator} is required, or use
 * any of its special operations, such as:
 *
 *

 *
{@link #immutableSortedCopy}
 *
{@link #isOrdered} / {@link #isStrictlyOrdered}
 *
{@link #min} / {@link #max}
 *

 *
 *
Understanding complex orderings

 *
 *
Complex chained orderings like the following example can be challenging to understand.
 *
 *
{@code
 * Ordering<Foo> ordering =
 *     Ordering.natural()
 *         .nullsFirst()
 *         .onResultOf(getBarFunction)
 *         .nullsLast();
 * }

 *
 * Note that each chaining method returns a new ordering instance which is backed by the previous
 * instance, but has the chance to act on values before handing off to that backing instance.
 * As a result, it usually helps to read chained ordering expressions backwards. For example,
 * when {@code compare} is called on the above ordering:
 *
 *

 *
First, if only one {@code Foo} is null, that null value is treated as greater
 *
Next, non-null {@code Foo} values are passed to {@code getBarFunction} (we will be
 *       comparing {@code Bar} values from now on)
 *
Next, if only one {@code Bar} is null, that null value is treated as lesser
 *
Finally, natural ordering is used (i.e. the result of {@code Bar.compareTo(Bar)} is
 *       returned)
 *

 *
 *
Alas, {@link #reverse} is a little different. As you read backwards through a chain and
 * encounter a call to {@code reverse}, continue working backwards until a result is determined, and
 * then reverse that result.
 *
 *
Additional notes

 *
 *
Except as noted, the orderings returned by the factory methods of this class are serializable
 * if and only if the provided instances that back them are. For example, if {@code ordering} and
 * {@code function} can themselves be serialized, then {@code ordering.onResultOf(function)} can as
 * well.
 *
 *
For Java 8 users

 *
 *
If you are using Java 8, this class is now obsolete. Most of its functionality is now provided
 * by {@link java.util.stream.Stream Stream} and by {@link Comparator} itself, and the rest can now
 * be found as static methods in our new {@link Comparators} class. See each method below for
 * further instructions. Whenever possible, you should change any references of type {@code
 * Ordering} to be of type {@code Comparator} instead. However, at this time we have no plan to
 * deprecate this class.
 *
 *
Many replacements involve adopting {@code Stream}, and these changes can sometimes make your
 * code verbose. Whenever following this advice, you should check whether {@code Stream} could be
 * adopted more comprehensively in your code; the end result may be quite a bit simpler.
 *
 *
See also

 *
 *
See the Guava User Guide article on {@code Ordering}.
 *
 * @author Jesse Wilson
 * @author Kevin Bourrillion
 * @since 2.0
 */
@GwtCompatible
public abstract class Ordering<T> implements Comparator<T> {
  // Natural order

  /**
   * Returns a serializable ordering that uses the natural order of the values. The ordering throws
   * a {@link NullPointerException} when passed a null parameter.
   *
   *
The type specification is {@code <C extends Comparable>}, instead of the technically correct
   * {@code <C extends Comparable<? super C>>}, to support legacy types from before Java 5.
   *
   *
Java 8 users: use {@link Comparator#naturalOrder} instead.
   */
  @GwtCompatible(serializable = true)
  @SuppressWarnings("unchecked") // TODO(kevinb): right way to explain this??
  public static <C extends Comparable> Ordering<C> natural() {
    return (Ordering<C>) NaturalOrdering.INSTANCE;
  }

  // Static factories

  /**
   * Returns an ordering based on an existing comparator instance. Note that it is
   * unnecessary to create a new anonymous inner class implementing {@code Comparator} just
   * to pass it in here. Instead, simply subclass {@code Ordering} and implement its {@code compare}
   * method directly.
   *
   *
Java 8 users: this class is now obsolete as explained in the class documentation, so
   * there is no need to use this method.
   *
   * @param comparator the comparator that defines the order
   * @return comparator itself if it is already an {@code Ordering}; otherwise an ordering that
   *     wraps that comparator
   */
  @GwtCompatible(serializable = true)
  public static <T> Ordering<T> from(Comparator<T> comparator) {
    return (comparator instanceof Ordering)
        ? (Ordering<T>) comparator
        : new ComparatorOrdering<T>(comparator);
  }

  /**
   * Simply returns its argument.
   *
   * @deprecated no need to use this
   */
  @GwtCompatible(serializable = true)
  @Deprecated
  public static <T> Ordering<T> from(Ordering<T> ordering) {
    return checkNotNull(ordering);
  }

  /**
   * Returns an ordering that compares objects according to the order in which they appear in the
   * given list. Only objects present in the list (according to {@link Object#equals}) may be
   * compared. This comparator imposes a "partial ordering" over the type {@code T}. Subsequent
   * changes to the {@code valuesInOrder} list will have no effect on the returned comparator. Null
   * values in the list are not supported.
   *
   *
The returned comparator throws a {@link ClassCastException} when it receives an input
   * parameter that isn't among the provided values.
   *
   *
The generated comparator is serializable if all the provided values are serializable.
   *
   * @param valuesInOrder the values that the returned comparator will be able to compare, in the
   *     order the comparator should induce
   * @return the comparator described above
   * @throws NullPointerException if any of the provided values is null
   * @throws IllegalArgumentException if {@code valuesInOrder} contains any duplicate values
   *     (according to {@link Object#equals})
   */
  // TODO(kevinb): provide replacement
  @GwtCompatible(serializable = true)
  public static <T> Ordering<T> explicit(List<T> valuesInOrder) {
    return new ExplicitOrdering<T>(valuesInOrder);
  }

  /**
   * Returns an ordering that compares objects according to the order in which they are given to
   * this method. Only objects present in the argument list (according to {@link Object#equals}) may
   * be compared. This comparator imposes a "partial ordering" over the type {@code T}. Null values
   * in the argument list are not supported.
   *
   *
The returned comparator throws a {@link ClassCastException} when it receives an input
   * parameter that isn't among the provided values.
   *
   *
The generated comparator is serializable if all the provided values are serializable.
   *
   * @param leastValue the value which the returned comparator should consider the "least" of all
   *     values
   * @param remainingValuesInOrder the rest of the values that the returned comparator will be able
   *     to compare, in the order the comparator should follow
   * @return the comparator described above
   * @throws NullPointerException if any of the provided values is null
   * @throws IllegalArgumentException if any duplicate values (according to {@link
   *     Object#equals(Object)}) are present among the method arguments
   */
  // TODO(kevinb): provide replacement
  @GwtCompatible(serializable = true)
  public static <T> Ordering<T> explicit(T leastValue, T... remainingValuesInOrder) {
    return explicit(Lists.asList(leastValue, remainingValuesInOrder));
  }

  // Ordering<Object> singletons

  /**
   * Returns an ordering which treats all values as equal, indicating "no ordering." Passing this
   * ordering to any stable sort algorithm results in no change to the order of elements.
   * Note especially that {@link #sortedCopy} and {@link #immutableSortedCopy} are stable, and in
   * the returned instance these are implemented by simply copying the source list.
   *
   *
Example:
   *
   *
{@code
   * Ordering.allEqual().nullsLast().sortedCopy(
   *     asList(t, null, e, s, null, t, null))
   * }

   *
   *
Assuming {@code t}, {@code e} and {@code s} are non-null, this returns {@code [t, e, s, t,
   * null, null, null]} regardless of the true comparison order of those three values (which might
   * not even implement {@link Comparable} at all).
   *
   *
Warning: by definition, this comparator is not consistent with equals (as
   * defined {@linkplain Comparator here}). Avoid its use in APIs, such as {@link
   * TreeSet#TreeSet(Comparator)}, where such consistency is expected.
   *
   *
The returned comparator is serializable.
   *
   *
Java 8 users: Use the lambda expression {@code (a, b) -> 0} instead (in certain cases
   * you may need to cast that to {@code Comparator<YourType>}).
   *
   * @since 13.0
   */
  @GwtCompatible(serializable = true)
  @SuppressWarnings("unchecked")
  public static Ordering<Object> allEqual() {
    return AllEqualOrdering.INSTANCE;
  }

  /**
   * Returns an ordering that compares objects by the natural ordering of their string
   * representations as returned by {@code toString()}. It does not support null values.
   *
   *
The comparator is serializable.
   *
   *
Java 8 users: Use {@code Comparator.comparing(Object::toString)} instead.
   */
  @GwtCompatible(serializable = true)
  public static Ordering<Object> usingToString() {
    return UsingToStringOrdering.INSTANCE;
  }

  /**
   * Returns an arbitrary ordering over all objects, for which {@code compare(a, b) == 0} implies
   * {@code a == b} (identity equality). There is no meaning whatsoever to the order imposed, but it
   * is constant for the life of the VM.
   *
   *
Because the ordering is identity-based, it is not "consistent with {@link
   * Object#equals(Object)}" as defined by {@link Comparator}. Use caution when building a {@link
   * SortedSet} or {@link SortedMap} from it, as the resulting collection will not behave exactly
   * according to spec.
   *
   *
This ordering is not serializable, as its implementation relies on {@link
   * System#identityHashCode(Object)}, so its behavior cannot be preserved across serialization.
   *
   * @since 2.0
   */
  // TODO(kevinb): copy to Comparators, etc.
  public static Ordering<Object> arbitrary() {
    return ArbitraryOrderingHolder.ARBITRARY_ORDERING;
  }

  private static class ArbitraryOrderingHolder {
    static final Ordering<Object> ARBITRARY_ORDERING = new ArbitraryOrdering();
  }

  @VisibleForTesting
  static class ArbitraryOrdering extends Ordering<Object> {

    private final AtomicInteger counter = new AtomicInteger(0);
    private final ConcurrentMap<Object, Integer> uids =
        Platform.tryWeakKeys(new MapMaker()).makeMap();

    private Integer getUid(Object obj) {
      Integer uid = uids.get(obj);
      if (uid == null) {
        // One or more integer values could be skipped in the event of a race
        // to generate a UID for the same object from multiple threads, but
        // that shouldn't be a problem.
        uid = counter.getAndIncrement();
        Integer alreadySet = uids.putIfAbsent(obj, uid);
        if (alreadySet != null) {
          uid = alreadySet;
        }
      }
      return uid;
    }

    @Override
    public int compare(Object left, Object right) {
      if (left == right) {
        return 0;
      } else if (left == null) {
        return -1;
      } else if (right == null) {
        return 1;
      }
      int leftCode = identityHashCode(left);
      int rightCode = identityHashCode(right);
      if (leftCode != rightCode) {
        return leftCode < rightCode ? -1 : 1;
      }

      // identityHashCode collision (rare, but not as rare as you'd think)
      int result = getUid(left).compareTo(getUid(right));
      if (result == 0) {
        throw new AssertionError(); // extremely, extremely unlikely.
      }
      return result;
    }

    @Override
    public String toString() {
      return "Ordering.arbitrary()";
    }

    /*
     * We need to be able to mock identityHashCode() calls for tests, because it
     * can take 1-10 seconds to find colliding objects. Mocking frameworks that
     * can do magic to mock static method calls still can't do so for a system
     * class, so we need the indirection. In production, Hotspot should still
     * recognize that the call is 1-morphic and should still be willing to
     * inline it if necessary.
     */
    int identityHashCode(Object object) {
      return System.identityHashCode(object);
    }
  }

  // Constructor

  /**
   * Constructs a new instance of this class (only invokable by the subclass constructor, typically
   * implicit).
   */
  protected Ordering() {}

  // Instance-based factories (and any static equivalents)

  /**
   * Returns the reverse of this ordering; the {@code Ordering} equivalent to {@link
   * Collections#reverseOrder(Comparator)}.
   *
   *
Java 8 users: Use {@code thisComparator.reversed()} instead.
   */
  // type parameter <S> lets us avoid the extra <String> in statements like:
  // Ordering<String> o = Ordering.<String>natural().reverse();
  @GwtCompatible(serializable = true)
  public <S extends T> Ordering<S> reverse() {
    return new ReverseOrdering<S>(this);
  }

  /**
   * Returns an ordering that treats {@code null} as less than all other values and uses {@code
   * this} to compare non-null values.
   *
   *
Java 8 users: Use {@code Comparator.nullsFirst(thisComparator)} instead.
   */
  // type parameter <S> lets us avoid the extra <String> in statements like:
  // Ordering<String> o = Ordering.<String>natural().nullsFirst();
  @GwtCompatible(serializable = true)
  public <S extends T> Ordering<S> nullsFirst() {
    return new NullsFirstOrdering<S>(this);
  }

  /**
   * Returns an ordering that treats {@code null} as greater than all other values and uses this
   * ordering to compare non-null values.
   *
   *
Java 8 users: Use {@code Comparator.nullsLast(thisComparator)} instead.
   */
  // type parameter <S> lets us avoid the extra <String> in statements like:
  // Ordering<String> o = Ordering.<String>natural().nullsLast();
  @GwtCompatible(serializable = true)
  public <S extends T> Ordering<S> nullsLast() {
    return new NullsLastOrdering<S>(this);
  }

  /**
   * Returns a new ordering on {@code F} which orders elements by first applying a function to them,
   * then comparing those results using {@code this}. For example, to compare objects by their
   * string forms, in a case-insensitive manner, use:
   *
   *
{@code
   * Ordering.from(String.CASE_INSENSITIVE_ORDER)
   *     .onResultOf(Functions.toStringFunction())
   * }

   *
   *
Java 8 users: Use {@code Comparator.comparing(function, thisComparator)} instead (you
   * can omit the comparator if it is the natural order).
   */
  @GwtCompatible(serializable = true)
  public <F> Ordering<F> onResultOf(Function<F, ? extends T> function) {
    return new ByFunctionOrdering<>(function, this);
  }

  <T2 extends T> Ordering<Entry<T2, ?>> onKeys() {
    return onResultOf(Maps.<T2>keyFunction());
  }

  /**
   * Returns an ordering which first uses the ordering {@code this}, but which in the event of a
   * "tie", then delegates to {@code secondaryComparator}. For example, to sort a bug list first by
   * status and second by priority, you might use {@code byStatus.compound(byPriority)}. For a
   * compound ordering with three or more components, simply chain multiple calls to this method.
   *
   *
An ordering produced by this method, or a chain of calls to this method, is equivalent to
   * one created using {@link Ordering#compound(Iterable)} on the same component comparators.
   *
   *
Java 8 users: Use {@code thisComparator.thenComparing(secondaryComparator)} instead.
   * Depending on what {@code secondaryComparator} is, one of the other overloads of {@code
   * thenComparing} may be even more useful.
   */
  @GwtCompatible(serializable = true)
  public  Ordering compound(Comparator<? super U> secondaryComparator) {
    return new CompoundOrdering(this, checkNotNull(secondaryComparator));
  }

  /**
   * Returns an ordering which tries each given comparator in order until a non-zero result is
   * found, returning that result, and returning zero only if all comparators return zero. The
   * returned ordering is based on the state of the {@code comparators} iterable at the time it was
   * provided to this method.
   *
   *
The returned ordering is equivalent to that produced using {@code
   * Ordering.from(comp1).compound(comp2).compound(comp3) . . .}.
   *
   *
Warning: Supplying an argument with undefined iteration order, such as a {@link
   * HashSet}, will produce non-deterministic results.
   *
   *
Java 8 users: Use a chain of calls to {@link Comparator#thenComparing(Comparator)},
   * or {@code comparatorCollection.stream().reduce(Comparator::thenComparing).get()} (if the
   * collection might be empty, also provide a default comparator as the {@code identity} parameter
   * to {@code reduce}).
   *
   * @param comparators the comparators to try in order
   */
  @GwtCompatible(serializable = true)
  public static <T> Ordering<T> compound(Iterable<? extends Comparator<? super T>> comparators) {
    return new CompoundOrdering<T>(comparators);
  }

  /**
   * Returns a new ordering which sorts iterables by comparing corresponding elements pairwise until
   * a nonzero result is found; imposes "dictionary order". If the end of one iterable is reached,
   * but not the other, the shorter iterable is considered to be less than the longer one. For
   * example, a lexicographical natural ordering over integers considers {@code [] < [1] < [1, 1] <
   * [1, 2] < [2]}.
   *
   *
Note that {@code ordering.lexicographical().reverse()} is not equivalent to {@code
   * ordering.reverse().lexicographical()} (consider how each would order {@code [1]} and {@code [1,
   * 1]}).
   *
   *
Java 8 users: Use {@link Comparators#lexicographical(Comparator)} instead.
   *
   * @since 2.0
   */
  @GwtCompatible(serializable = true)
  // type parameter <S> lets us avoid the extra <String> in statements like:
  // Ordering<Iterable<String>> o =
  //     Ordering.<String>natural().lexicographical();
  public <S extends T> Ordering<Iterable<S>> lexicographical() {
    /*
     * Note that technically the returned ordering should be capable of
     * handling not just {@code Iterable<S>} instances, but also any {@code
     * Iterable<? extends S>}. However, the need for this comes up so rarely
     * that it doesn't justify making everyone else deal with the very ugly
     * wildcard.
     */
    return new LexicographicalOrdering<S>(this);
  }

  // Regular instance methods

  // Override to add @Nullable
  @CanIgnoreReturnValue // TODO(kak): Consider removing this
  @Override
  public abstract int compare(@Nullable T left, @Nullable T right);

  /**
   * Returns the least of the specified values according to this ordering. If there are multiple
   * least values, the first of those is returned. The iterator will be left exhausted: its {@code
   * hasNext()} method will return {@code false}.
   *
   *
Java 8 users: Use {@code Streams.stream(iterator).min(thisComparator).get()} instead
   * (but note that it does not guarantee which tied minimum element is returned).
   *
   * @param iterator the iterator whose minimum element is to be determined
   * @throws NoSuchElementException if {@code iterator} is empty
   * @throws ClassCastException if the parameters are not mutually comparable under this
   *     ordering.
   * @since 11.0
   */
  public <E extends T> E min(Iterator<E> iterator) {
    // let this throw NoSuchElementException as necessary
    E minSoFar = iterator.next();

    while (iterator.hasNext()) {
      minSoFar = min(minSoFar, iterator.next());
    }

    return minSoFar;
  }

  /**
   * Returns the least of the specified values according to this ordering. If there are multiple
   * least values, the first of those is returned.
   *
   *
Java 8 users: If {@code iterable} is a {@link Collection}, use {@code
   * Collections.min(collection, thisComparator)} instead. Otherwise, use {@code
   * Streams.stream(iterable).min(thisComparator).get()} instead. Note that these alternatives do
   * not guarantee which tied minimum element is returned)
   *
   * @param iterable the iterable whose minimum element is to be determined
   * @throws NoSuchElementException if {@code iterable} is empty
   * @throws ClassCastException if the parameters are not mutually comparable under this
   *     ordering.
   */
  public <E extends T> E min(Iterable<E> iterable) {
    return min(iterable.iterator());
  }

  /**
   * Returns the lesser of the two values according to this ordering. If the values compare as 0,
   * the first is returned.
   *
   *
Implementation note: this method is invoked by the default implementations of the
   * other {@code min} overloads, so overriding it will affect their behavior.
   *
   *
Java 8 users: Use {@code Collections.min(Arrays.asList(a, b), thisComparator)}
   * instead (but note that it does not guarantee which tied minimum element is returned).
   *
   * @param a value to compare, returned if less than or equal to b.
   * @param b value to compare.
   * @throws ClassCastException if the parameters are not mutually comparable under this
   *     ordering.
   */
  public <E extends T> E min(@Nullable E a, @Nullable E b) {
    return (compare(a, b) <= 0) ? a : b;
  }

  /**
   * Returns the least of the specified values according to this ordering. If there are multiple
   * least values, the first of those is returned.
   *
   *
Java 8 users: Use {@code Collections.min(Arrays.asList(a, b, c...), thisComparator)}
   * instead (but note that it does not guarantee which tied minimum element is returned).
   *
   * @param a value to compare, returned if less than or equal to the rest.
   * @param b value to compare
   * @param c value to compare
   * @param rest values to compare
   * @throws ClassCastException if the parameters are not mutually comparable under this
   *     ordering.
   */
  public <E extends T> E min(@Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
    E minSoFar = min(min(a, b), c);

    for (E r : rest) {
      minSoFar = min(minSoFar, r);
    }

    return minSoFar;
  }

  /**
   * Returns the greatest of the specified values according to this ordering. If there are multiple
   * greatest values, the first of those is returned. The iterator will be left exhausted: its
   * {@code hasNext()} method will return {@code false}.
   *
   *
Java 8 users: Continue to use this method for now. Use {@code
   * Streams.stream(iterator).max(thisComparator).get()} instead (but note that it does not
   * guarantee which tied maximum element is returned).
   *
   * @param iterator the iterator whose maximum element is to be determined
   * @throws NoSuchElementException if {@code iterator} is empty
   * @throws ClassCastException if the parameters are not mutually comparable under this
   *     ordering.
   * @since 11.0
   */
  public <E extends T> E max(Iterator<E> iterator) {
    // let this throw NoSuchElementException as necessary
    E maxSoFar = iterator.next();

    while (iterator.hasNext()) {
      maxSoFar = max(maxSoFar, iterator.next());
    }

    return maxSoFar;
  }

  /**
   * Returns the greatest of the specified values according to this ordering. If there are multiple
   * greatest values, the first of those is returned.
   *
   *
Java 8 users: If {@code iterable} is a {@link Collection}, use {@code
   * Collections.max(collection, thisComparator)} instead. Otherwise, use {@code
   * Streams.stream(iterable).max(thisComparator).get()} instead. Note that these alternatives do
   * not guarantee which tied maximum element is returned)
   *
   * @param iterable the iterable whose maximum element is to be determined
   * @throws NoSuchElementException if {@code iterable} is empty
   * @throws ClassCastException if the parameters are not mutually comparable under this
   *     ordering.
   */
  public <E extends T> E max(Iterable<E> iterable) {
    return max(iterable.iterator());
  }

  /**
   * Returns the greater of the two values according to this ordering. If the values compare as 0,
   * the first is returned.
   *
   *
Implementation note: this method is invoked by the default implementations of the
   * other {@code max} overloads, so overriding it will affect their behavior.
   *
   *
Java 8 users: Use {@code Collections.max(Arrays.asList(a, b), thisComparator)}
   * instead (but note that it does not guarantee which tied maximum element is returned).
   *
   * @param a value to compare, returned if greater than or equal to b.
   * @param b value to compare.
   * @throws ClassCastException if the parameters are not mutually comparable under this
   *     ordering.
   */
  public <E extends T> E max(@Nullable E a, @Nullable E b) {
    return (compare(a, b) >= 0) ? a : b;
  }

  /**
   * Returns the greatest of the specified values according to this ordering. If there are multiple
   * greatest values, the first of those is returned.
   *
   *
Java 8 users: Use {@code Collections.max(Arrays.asList(a, b, c...), thisComparator)}
   * instead (but note that it does not guarantee which tied maximum element is returned).
   *
   * @param a value to compare, returned if greater than or equal to the rest.
   * @param b value to compare
   * @param c value to compare
   * @param rest values to compare
   * @throws ClassCastException if the parameters are not mutually comparable under this
   *     ordering.
   */
  public <E extends T> E max(@Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
    E maxSoFar = max(max(a, b), c);

    for (E r : rest) {
      maxSoFar = max(maxSoFar, r);
    }

    return maxSoFar;
  }

  /**
   * Returns the {@code k} least elements of the given iterable according to this ordering, in order
   * from least to greatest. If there are fewer than {@code k} elements present, all will be
   * included.
   *
   *
The implementation does not necessarily use a stable sorting algorithm; when multiple
   * elements are equivalent, it is undefined which will come first.
   *
   *
Java 8 users: Use {@code Streams.stream(iterable).collect(Comparators.least(k,
   * thisComparator))} instead.
   *
   * @return an immutable {@code RandomAccess} list of the {@code k} least elements in ascending
   *     order
   * @throws IllegalArgumentException if {@code k} is negative
   * @since 8.0
   */
  public <E extends T> List<E> leastOf(Iterable<E> iterable, int k) {
    if (iterable instanceof Collection) {
      Collection<E> collection = (Collection<E>) iterable;
      if (collection.size() <= 2L * k) {
        // In this case, just dumping the collection to an array and sorting is
        // faster than using the implementation for Iterator, which is
        // specialized for k much smaller than n.

        @SuppressWarnings("unchecked") // c only contains E's and doesn't escape
        E[] array = (E[]) collection.toArray();
        Arrays.sort(array, this);
        if (array.length > k) {
          array = Arrays.copyOf(array, k);
        }
        return Collections.unmodifiableList(Arrays.asList(array));
      }
    }
    return leastOf(iterable.iterator(), k);
  }

  /**
   * Returns the {@code k} least elements from the given iterator according to this ordering, in
   * order from least to greatest. If there are fewer than {@code k} elements present, all will be
   * included.
   *
   *
The implementation does not necessarily use a stable sorting algorithm; when multiple
   * elements are equivalent, it is undefined which will come first.
   *
   *
Java 8 users: Use {@code Streams.stream(iterator).collect(Comparators.least(k,
   * thisComparator))} instead.
   *
   * @return an immutable {@code RandomAccess} list of the {@code k} least elements in ascending
   *     order
   * @throws IllegalArgumentException if {@code k} is negative
   * @since 14.0
   */
  public <E extends T> List<E> leastOf(Iterator<E> iterator, int k) {
    checkNotNull(iterator);
    checkNonnegative(k, "k");

    if (k == 0 || !iterator.hasNext()) {
      return Collections.emptyList();
    } else if (k >= Integer.MAX_VALUE / 2) {
      // k is really large; just do a straightforward sorted-copy-and-sublist
      ArrayList<E> list = Lists.newArrayList(iterator);
      Collections.sort(list, this);
      if (list.size() > k) {
        list.subList(k, list.size()).clear();
      }
      list.trimToSize();
      return Collections.unmodifiableList(list);
    } else {
      TopKSelector<E> selector = TopKSelector.least(k, this);
      selector.offerAll(iterator);
      return selector.topK();
    }
  }

  /**
   * Returns the {@code k} greatest elements of the given iterable according to this ordering, in
   * order from greatest to least. If there are fewer than {@code k} elements present, all will be
   * included.
   *
   *
The implementation does not necessarily use a stable sorting algorithm; when multiple
   * elements are equivalent, it is undefined which will come first.
   *
   *
Java 8 users: Use {@code Streams.stream(iterable).collect(Comparators.greatest(k,
   * thisComparator))} instead.
   *
   * @return an immutable {@code RandomAccess} list of the {@code k} greatest elements in
   *     descending order
   * @throws IllegalArgumentException if {@code k} is negative
   * @since 8.0
   */
  public <E extends T> List<E> greatestOf(Iterable<E> iterable, int k) {
    // TODO(kevinb): see if delegation is hurting performance noticeably
    // TODO(kevinb): if we change this implementation, add full unit tests.
    return reverse().leastOf(iterable, k);
  }

  /**
   * Returns the {@code k} greatest elements from the given iterator according to this ordering, in
   * order from greatest to least. If there are fewer than {@code k} elements present, all will be
   * included.
   *
   *
The implementation does not necessarily use a stable sorting algorithm; when multiple
   * elements are equivalent, it is undefined which will come first.
   *
   *
Java 8 users: Use {@code Streams.stream(iterator).collect(Comparators.greatest(k,
   * thisComparator))} instead.
   *
   * @return an immutable {@code RandomAccess} list of the {@code k} greatest elements in
   *     descending order
   * @throws IllegalArgumentException if {@code k} is negative
   * @since 14.0
   */
  public <E extends T> List<E> greatestOf(Iterator<E> iterator, int k) {
    return reverse().leastOf(iterator, k);
  }

  /**
   * Returns a mutable list containing {@code elements} sorted by this ordering; use this
   * only when the resulting list may need further modification, or may contain {@code null}. The
   * input is not modified. The returned list is serializable and has random access.
   *
   *
Unlike {@link Sets#newTreeSet(Iterable)}, this method does not discard elements that are
   * duplicates according to the comparator. The sort performed is stable, meaning that such
   * elements will appear in the returned list in the same order they appeared in {@code elements}.
   *
   *
Performance note: According to our
   * benchmarking
   * on Open JDK 7, {@link #immutableSortedCopy} generally performs better (in both time and space)
   * than this method, and this method in turn generally performs better than copying the list and
   * calling {@link Collections#sort(List)}.
   */
  // TODO(kevinb): rerun benchmarks including new options
  public <E extends T> List<E> sortedCopy(Iterable<E> elements) {
    @SuppressWarnings("unchecked") // does not escape, and contains only E's
    E[] array = (E[]) Iterables.toArray(elements);
    Arrays.sort(array, this);
    return Lists.newArrayList(Arrays.asList(array));
  }

  /**
   * Returns an immutable list containing {@code elements} sorted by this ordering. The input
   * is not modified.
   *
   *
Unlike {@link Sets#newTreeSet(Iterable)}, this method does not discard elements that are
   * duplicates according to the comparator. The sort performed is stable, meaning that such
   * elements will appear in the returned list in the same order they appeared in {@code elements}.
   *
   *
Performance note: According to our
   * benchmarking
   * on Open JDK 7, this method is the most efficient way to make a sorted copy of a collection.
   *
   * @throws NullPointerException if any element of {@code elements} is {@code null}
   * @since 3.0
   */
  // TODO(kevinb): rerun benchmarks including new options
  public <E extends T> ImmutableList<E> immutableSortedCopy(Iterable<E> elements) {
    return ImmutableList.sortedCopyOf(this, elements);
  }

  /**
   * Returns {@code true} if each element in {@code iterable} after the first is greater than or
   * equal to the element that preceded it, according to this ordering. Note that this is always
   * true when the iterable has fewer than two elements.
   *
   *
Java 8 users: Use the equivalent {@link Comparators#isInOrder(Iterable, Comparator)}
   * instead, since the rest of {@code Ordering} is mostly obsolete (as explained in the class
   * documentation).
   */
  public boolean isOrdered(Iterable<? extends T> iterable) {
    Iterator<? extends T> it = iterable.iterator();
    if (it.hasNext()) {
      T prev = it.next();
      while (it.hasNext()) {
        T next = it.next();
        if (compare(prev, next) > 0) {
          return false;
        }
        prev = next;
      }
    }
    return true;
  }

  /**
   * Returns {@code true} if each element in {@code iterable} after the first is strictly
   * greater than the element that preceded it, according to this ordering. Note that this is always
   * true when the iterable has fewer than two elements.
   *
   *
Java 8 users: Use the equivalent {@link Comparators#isInStrictOrder(Iterable,
   * Comparator)} instead, since the rest of {@code Ordering} is mostly obsolete (as explained in
   * the class documentation).
   */
  public boolean isStrictlyOrdered(Iterable<? extends T> iterable) {
    Iterator<? extends T> it = iterable.iterator();
    if (it.hasNext()) {
      T prev = it.next();
      while (it.hasNext()) {
        T next = it.next();
        if (compare(prev, next) >= 0) {
          return false;
        }
        prev = next;
      }
    }
    return true;
  }

  /**
   * {@link Collections#binarySearch(List, Object, Comparator) Searches} {@code sortedList} for
   * {@code key} using the binary search algorithm. The list must be sorted using this ordering.
   *
   * @param sortedList the list to be searched
   * @param key the key to be searched for
   * @deprecated Use {@link Collections#binarySearch(List, Object, Comparator)} directly.
   */
  @Deprecated
  public int binarySearch(List<? extends T> sortedList, @Nullable T key) {
    return Collections.binarySearch(sortedList, key, this);
  }

  /**
   * Exception thrown by a {@link Ordering#explicit(List)} or {@link Ordering#explicit(Object,
   * Object[])} comparator when comparing a value outside the set of values it can compare.
   * Extending {@link ClassCastException} may seem odd, but it is required.
   */
  @VisibleForTesting
  static class IncomparableValueException extends ClassCastException {
    final Object value;

    IncomparableValueException(Object value) {
      super("Cannot compare value: " + value);
      this.value = value;
    }

    private static final long serialVersionUID = 0;
  }

  // Never make these public
  static final int LEFT_IS_GREATER = 1;
  static final int RIGHT_IS_GREATER = -1;
}


/*
 * Copyright (C) 2013 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 static com.google.common.collect.CollectPreconditions.checkNonnegative;

import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Supplier;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * A builder for a multimap implementation that allows customization of the backing map and value
 * collection implementations used in a particular multimap.
 *
 *
This can be used to easily configure multimap data structure implementations not provided
 * explicitly in {@code com.google.common.collect}, for example:
 *
 *
{@code
 * ListMultimap<String, Integer> treeListMultimap =
 *     MultimapBuilder.treeKeys().arrayListValues().build();
 * SetMultimap<Integer, MyEnum> hashEnumMultimap =
 *     MultimapBuilder.hashKeys().enumSetValues(MyEnum.class).build();
 * }

 *
 *
{@code MultimapBuilder} instances are immutable. Invoking a configuration method has no effect
 * on the receiving instance; you must store and use the new builder instance it returns instead.
 *
 *
The generated multimaps are serializable if the key and value types are serializable, unless
 * stated otherwise in one of the configuration methods.
 *
 * @author Louis Wasserman
 * @param <K0> An upper bound on the key type of the generated multimap.
 * @param <V0> An upper bound on the value type of the generated multimap.
 * @since 16.0
 */
@GwtCompatible
public abstract class MultimapBuilder<K0, V0> {
  /*
   * Leaving K and V as upper bounds rather than the actual key and value types allows type
   * parameters to be left implicit more often. CacheBuilder uses the same technique.
   */

  private MultimapBuilder() {}

  private static final int DEFAULT_EXPECTED_KEYS = 8;

  /** Uses a hash table to map keys to value collections. */
  public static MultimapBuilderWithKeys<Object> hashKeys() {
    return hashKeys(DEFAULT_EXPECTED_KEYS);
  }

  /**
   * Uses a hash table to map keys to value collections, initialized to expect the specified number
   * of keys.
   *
   * @throws IllegalArgumentException if {@code expectedKeys < 0}
   */
  public static MultimapBuilderWithKeys<Object> hashKeys(final int expectedKeys) {
    checkNonnegative(expectedKeys, "expectedKeys");
    return new MultimapBuilderWithKeys<Object>() {
      @Override
      <K, V> Map<K, Collection<V>> createMap() {
        return Platform.newHashMapWithExpectedSize(expectedKeys);
      }
    };
  }

  /**
   * Uses a hash table to map keys to value collections.
   *
   *
The collections returned by {@link Multimap#keySet()}, {@link Multimap#keys()}, and {@link
   * Multimap#asMap()} will iterate through the keys in the order that they were first added to the
   * multimap, save that if all values associated with a key are removed and then the key is added
   * back into the multimap, that key will come last in the key iteration order.
   */
  public static MultimapBuilderWithKeys<Object> linkedHashKeys() {
    return linkedHashKeys(DEFAULT_EXPECTED_KEYS);
  }

  /**
   * Uses an hash table to map keys to value collections, initialized to expect the specified number
   * of keys.
   *
   *
The collections returned by {@link Multimap#keySet()}, {@link Multimap#keys()}, and {@link
   * Multimap#asMap()} will iterate through the keys in the order that they were first added to the
   * multimap, save that if all values associated with a key are removed and then the key is added
   * back into the multimap, that key will come last in the key iteration order.
   */
  public static MultimapBuilderWithKeys<Object> linkedHashKeys(final int expectedKeys) {
    checkNonnegative(expectedKeys, "expectedKeys");
    return new MultimapBuilderWithKeys<Object>() {
      @Override
      <K, V> Map<K, Collection<V>> createMap() {
        return Platform.newLinkedHashMapWithExpectedSize(expectedKeys);
      }
    };
  }

  /**
   * Uses a naturally-ordered {@link TreeMap} to map keys to value collections.
   *
   *
The collections returned by {@link Multimap#keySet()}, {@link Multimap#keys()}, and {@link
   * Multimap#asMap()} will iterate through the keys in sorted order.
   *
   *
For all multimaps generated by the resulting builder, the {@link Multimap#keySet()} can be
   * safely cast to a {@link java.util.SortedSet}, and the {@link Multimap#asMap()} can safely be
   * cast to a {@link java.util.SortedMap}.
   */
  @SuppressWarnings("rawtypes")
  public static MultimapBuilderWithKeys<Comparable> treeKeys() {
    return treeKeys(Ordering.natural());
  }

  /**
   * Uses a {@link TreeMap} sorted by the specified comparator to map keys to value collections.
   *
   *
The collections returned by {@link Multimap#keySet()}, {@link Multimap#keys()}, and {@link
   * Multimap#asMap()} will iterate through the keys in sorted order.
   *
   *
For all multimaps generated by the resulting builder, the {@link Multimap#keySet()} can be
   * safely cast to a {@link java.util.SortedSet}, and the {@link Multimap#asMap()} can safely be
   * cast to a {@link java.util.SortedMap}.
   *
   *
Multimaps generated by the resulting builder will not be serializable if {@code comparator}
   * is not serializable.
   */
  public static <K0> MultimapBuilderWithKeys<K0> treeKeys(final Comparator<K0> comparator) {
    checkNotNull(comparator);
    return new MultimapBuilderWithKeys<K0>() {
      @Override
      <K extends K0, V> Map<K, Collection<V>> createMap() {
        return new TreeMap<>(comparator);
      }
    };
  }

  /**
   * Uses an {@link EnumMap} to map keys to value collections.
   *
   * @since 16.0
   */
  public static <K0 extends Enum<K0>> MultimapBuilderWithKeys<K0> enumKeys(
      final Class<K0> keyClass) {
    checkNotNull(keyClass);
    return new MultimapBuilderWithKeys<K0>() {
      @SuppressWarnings("unchecked")
      @Override
      <K extends K0, V> Map<K, Collection<V>> createMap() {
        // K must actually be K0, since enums are effectively final
        // (their subclasses are inaccessible)
        return (Map<K, Collection<V>>) new EnumMap<K0, Collection<V>>(keyClass);
      }
    };
  }

  private static final class ArrayListSupplier<V> implements Supplier<List<V>>, Serializable {
    private final int expectedValuesPerKey;

    ArrayListSupplier(int expectedValuesPerKey) {
      this.expectedValuesPerKey = checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
    }

    @Override
    public List<V> get() {
      return new ArrayList<V>(expectedValuesPerKey);
    }
  }

  private enum LinkedListSupplier implements Supplier<List<Object>> {
    INSTANCE;

    public static <V> Supplier<List<V>> instance() {
      // Each call generates a fresh LinkedList, which can serve as a List<V> for any V.
      @SuppressWarnings({"rawtypes", "unchecked"})
      Supplier<List<V>> result = (Supplier) INSTANCE;
      return result;
    }

    @Override
    public List<Object> get() {
      return new LinkedList<>();
    }
  }

  private static final class HashSetSupplier<V> implements Supplier<Set<V>>, Serializable {
    private final int expectedValuesPerKey;

    HashSetSupplier(int expectedValuesPerKey) {
      this.expectedValuesPerKey = checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
    }

    @Override
    public Set<V> get() {
      return Platform.newHashSetWithExpectedSize(expectedValuesPerKey);
    }
  }

  private static final class LinkedHashSetSupplier<V> implements Supplier<Set<V>>, Serializable {
    private final int expectedValuesPerKey;

    LinkedHashSetSupplier(int expectedValuesPerKey) {
      this.expectedValuesPerKey = checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
    }

    @Override
    public Set<V> get() {
      return Platform.newLinkedHashSetWithExpectedSize(expectedValuesPerKey);
    }
  }

  private static final class TreeSetSupplier<V> implements Supplier<SortedSet<V>>, Serializable {
    private final Comparator<? super V> comparator;

    TreeSetSupplier(Comparator<? super V> comparator) {
      this.comparator = checkNotNull(comparator);
    }

    @Override
    public SortedSet<V> get() {
      return new TreeSet<V>(comparator);
    }
  }

  private static final class EnumSetSupplier<V extends Enum<V>>
      implements Supplier<Set<V>>, Serializable {
    private final Class<V> clazz;

    EnumSetSupplier(Class<V> clazz) {
      this.clazz = checkNotNull(clazz);
    }

    @Override
    public Set<V> get() {
      return EnumSet.noneOf(clazz);
    }
  }

  /**
   * An intermediate stage in a {@link MultimapBuilder} in which the key-value collection map
   * implementation has been specified, but the value collection implementation has not.
   *
   * @param <K0> The upper bound on the key type of the generated multimap.
   * @since 16.0
   */
  public abstract static class MultimapBuilderWithKeys<K0> {

    private static final int DEFAULT_EXPECTED_VALUES_PER_KEY = 2;

    MultimapBuilderWithKeys() {}

    abstract <K extends K0, V> Map<K, Collection<V>> createMap();

    /** Uses an {@link ArrayList} to store value collections. */
    public ListMultimapBuilder<K0, Object> arrayListValues() {
      return arrayListValues(DEFAULT_EXPECTED_VALUES_PER_KEY);
    }

    /**
     * Uses an {@link ArrayList} to store value collections, initialized to expect the specified
     * number of values per key.
     *
     * @throws IllegalArgumentException if {@code expectedValuesPerKey < 0}
     */
    public ListMultimapBuilder<K0, Object> arrayListValues(final int expectedValuesPerKey) {
      checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
      return new ListMultimapBuilder<K0, Object>() {
        @Override
        public <K extends K0, V> ListMultimap<K, V> build() {
          return Multimaps.newListMultimap(
              MultimapBuilderWithKeys.this.<K, V>createMap(),
              new ArrayListSupplier<V>(expectedValuesPerKey));
        }
      };
    }

    /** Uses a {@link LinkedList} to store value collections. */
    public ListMultimapBuilder<K0, Object> linkedListValues() {
      return new ListMultimapBuilder<K0, Object>() {
        @Override
        public <K extends K0, V> ListMultimap<K, V> build() {
          return Multimaps.newListMultimap(
              MultimapBuilderWithKeys.this.<K, V>createMap(), LinkedListSupplier.<V>instance());
        }
      };
    }

    /** Uses a hash-based {@code Set} to store value collections. */
    public SetMultimapBuilder<K0, Object> hashSetValues() {
      return hashSetValues(DEFAULT_EXPECTED_VALUES_PER_KEY);
    }

    /**
     * Uses a hash-based {@code Set} to store value collections, initialized to expect the specified
     * number of values per key.
     *
     * @throws IllegalArgumentException if {@code expectedValuesPerKey < 0}
     */
    public SetMultimapBuilder<K0, Object> hashSetValues(final int expectedValuesPerKey) {
      checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
      return new SetMultimapBuilder<K0, Object>() {
        @Override
        public <K extends K0, V> SetMultimap<K, V> build() {
          return Multimaps.newSetMultimap(
              MultimapBuilderWithKeys.this.<K, V>createMap(),
              new HashSetSupplier<V>(expectedValuesPerKey));
        }
      };
    }

    /** Uses an insertion-ordered hash-based {@code Set} to store value collections. */
    public SetMultimapBuilder<K0, Object> linkedHashSetValues() {
      return linkedHashSetValues(DEFAULT_EXPECTED_VALUES_PER_KEY);
    }

    /**
     * Uses an insertion-ordered hash-based {@code Set} to store value collections, initialized to
     * expect the specified number of values per key.
     *
     * @throws IllegalArgumentException if {@code expectedValuesPerKey < 0}
     */
    public SetMultimapBuilder<K0, Object> linkedHashSetValues(final int expectedValuesPerKey) {
      checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
      return new SetMultimapBuilder<K0, Object>() {
        @Override
        public <K extends K0, V> SetMultimap<K, V> build() {
          return Multimaps.newSetMultimap(
              MultimapBuilderWithKeys.this.<K, V>createMap(),
              new LinkedHashSetSupplier<V>(expectedValuesPerKey));
        }
      };
    }

    /** Uses a naturally-ordered {@link TreeSet} to store value collections. */
    @SuppressWarnings("rawtypes")
    public SortedSetMultimapBuilder<K0, Comparable> treeSetValues() {
      return treeSetValues(Ordering.natural());
    }

    /**
     * Uses a {@link TreeSet} ordered by the specified comparator to store value collections.
     *
     *
Multimaps generated by the resulting builder will not be serializable if {@code
     * comparator} is not serializable.
     */
    public <V0> SortedSetMultimapBuilder<K0, V0> treeSetValues(final Comparator<V0> comparator) {
      checkNotNull(comparator, "comparator");
      return new SortedSetMultimapBuilder<K0, V0>() {
        @Override
        public <K extends K0, V extends V0> SortedSetMultimap<K, V> build() {
          return Multimaps.newSortedSetMultimap(
              MultimapBuilderWithKeys.this.<K, V>createMap(), new TreeSetSupplier<V>(comparator));
        }
      };
    }

    /** Uses an {@link EnumSet} to store value collections. */
    public <V0 extends Enum<V0>> SetMultimapBuilder<K0, V0> enumSetValues(
        final Class<V0> valueClass) {
      checkNotNull(valueClass, "valueClass");
      return new SetMultimapBuilder<K0, V0>() {
        @Override
        public <K extends K0, V extends V0> SetMultimap<K, V> build() {
          // V must actually be V0, since enums are effectively final
          // (their subclasses are inaccessible)
          @SuppressWarnings({"unchecked", "rawtypes"})
          Supplier<Set<V>> factory = (Supplier) new EnumSetSupplier<V0>(valueClass);
          return Multimaps.newSetMultimap(MultimapBuilderWithKeys.this.<K, V>createMap(), factory);
        }
      };
    }
  }

  /** Returns a new, empty {@code Multimap} with the specified implementation. */
  public abstract <K extends K0, V extends V0> Multimap<K, V> build();

  /**
   * Returns a {@code Multimap} with the specified implementation, initialized with the entries of
   * {@code multimap}.
   */
  public <K extends K0, V extends V0> Multimap<K, V> build(
      Multimap<? extends K, ? extends V> multimap) {
    Multimap<K, V> result = build();
    result.putAll(multimap);
    return result;
  }

  /**
   * A specialization of {@link MultimapBuilder} that generates {@link ListMultimap} instances.
   *
   * @since 16.0
   */
  public abstract static class ListMultimapBuilder<K0, V0> extends MultimapBuilder<K0, V0> {
    ListMultimapBuilder() {}

    @Override
    public abstract <K extends K0, V extends V0> ListMultimap<K, V> build();

    @Override
    public <K extends K0, V extends V0> ListMultimap<K, V> build(
        Multimap<? extends K, ? extends V> multimap) {
      return (ListMultimap<K, V>) super.build(multimap);
    }
  }

  /**
   * A specialization of {@link MultimapBuilder} that generates {@link SetMultimap} instances.
   *
   * @since 16.0
   */
  public abstract static class SetMultimapBuilder<K0, V0> extends MultimapBuilder<K0, V0> {
    SetMultimapBuilder() {}

    @Override
    public abstract <K extends K0, V extends V0> SetMultimap<K, V> build();

    @Override
    public <K extends K0, V extends V0> SetMultimap<K, V> build(
        Multimap<? extends K, ? extends V> multimap) {
      return (SetMultimap<K, V>) super.build(multimap);
    }
  }

  /**
   * A specialization of {@link MultimapBuilder} that generates {@link SortedSetMultimap} instances.
   *
   * @since 16.0
   */
  public abstract static class SortedSetMultimapBuilder<K0, V0> extends SetMultimapBuilder<K0, V0> {
    SortedSetMultimapBuilder() {}

    @Override
    public abstract <K extends K0, V extends V0> SortedSetMultimap<K, V> build();

    @Override
    public <K extends K0, V extends V0> SortedSetMultimap<K, V> build(
        Multimap<? extends K, ? extends V> multimap) {
      return (SortedSetMultimap<K, V>) super.build(multimap);
    }
  }
}


/*
 * 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.base;

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

import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import java.util.Map;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

/**
 * Static utility methods pertaining to {@code com.google.common.base.Function} instances; see that
 * class for information about migrating to {@code java.util.function}.
 *
 *
All methods return serializable functions as long as they're given serializable parameters.
 *
 *
See the Guava User Guide article on the use of {@code Function}.
 *
 * @author Mike Bostock
 * @author Jared Levy
 * @since 2.0
 */
@GwtCompatible
public final class Functions {
  private Functions() {}

  /**
   * A function equivalent to the method reference {@code Object::toString}, for users not yet using
   * Java 8. The function simply invokes {@code toString} on its argument and returns the result. It
   * throws a {@link NullPointerException} on null input.
   *
   *
Warning: The returned function may not be consistent with equals (as
   * documented at {@link Function#apply}). For example, this function yields different results for
   * the two equal instances {@code ImmutableSet.of(1, 2)} and {@code ImmutableSet.of(2, 1)}.
   *
   *
Warning: as with all function types in this package, avoid depending on the specific
   * {@code equals}, {@code hashCode} or {@code toString} behavior of the returned function. A
   * future migration to {@code java.util.function} will not preserve this behavior.
   *
   *
For Java 8 users: use the method reference {@code Object::toString} instead. In the
   * future, when this class requires Java 8, this method will be deprecated. See {@link Function}
   * for more important information about the Java 8 transition.
   */
  public static Function<Object, String> toStringFunction() {
    return ToStringFunction.INSTANCE;
  }

  // enum singleton pattern
  private enum ToStringFunction implements Function<Object, String> {
    INSTANCE;

    @Override
    public String apply(Object o) {
      checkNotNull(o); // eager for GWT.
      return o.toString();
    }

    @Override
    public String toString() {
      return "Functions.toStringFunction()";
    }
  }

  /** Returns the identity function. */
  // implementation is "fully variant"; E has become a "pass-through" type
  @SuppressWarnings("unchecked")
  public static <E> Function<E, E> identity() {
    return (Function<E, E>) IdentityFunction.INSTANCE;
  }

  // enum singleton pattern
  private enum IdentityFunction implements Function<Object, Object> {
    INSTANCE;

    @Override
    @NullableDecl
    public Object apply(@NullableDecl Object o) {
      return o;
    }

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

  /**
   * Returns a function which performs a map lookup. The returned function throws an {@link
   * IllegalArgumentException} if given a key that does not exist in the map. See also {@link
   * #forMap(Map, Object)}, which returns a default value in this case.
   *
   *
Note: if {@code map} is a {@link com.google.common.collect.BiMap BiMap} (or can be one), you
   * can use {@link com.google.common.collect.Maps#asConverter Maps.asConverter} instead to get a
   * function that also supports reverse conversion.
   *
   *
Java 8 users: if you are okay with {@code null} being returned for an unrecognized
   * key (instead of an exception being thrown), you can use the method reference {@code map::get}
   * instead.
   */
  public static <K, V> Function<K, V> forMap(Map<K, V> map) {
    return new FunctionForMapNoDefault<>(map);
  }

  /**
   * Returns a function which performs a map lookup with a default value. The function created by
   * this method returns {@code defaultValue} for all inputs that do not belong to the map's key
   * set. See also {@link #forMap(Map)}, which throws an exception in this case.
   *
   *
Java 8 users: you can just write the lambda expression {@code k ->
   * map.getWithDefault(k, defaultValue)} instead.
   *
   * @param map source map that determines the function behavior
   * @param defaultValue the value to return for inputs that aren't map keys
   * @return function that returns {@code map.get(a)} when {@code a} is a key, or {@code
   *     defaultValue} otherwise
   */
  public static <K, V> Function<K, V> forMap(
      Map<K, ? extends V> map, @NullableDecl V defaultValue) {
    return new ForMapWithDefault<>(map, defaultValue);
  }

  private static class FunctionForMapNoDefault<K, V> implements Function<K, V>, Serializable {
    final Map<K, V> map;

    FunctionForMapNoDefault(Map<K, V> map) {
      this.map = checkNotNull(map);
    }

    @Override
    public V apply(@NullableDecl K key) {
      V result = map.get(key);
      checkArgument(result != null || map.containsKey(key), "Key '%s' not present in map", key);
      return result;
    }

    @Override
    public boolean equals(@NullableDecl Object o) {
      if (o instanceof FunctionForMapNoDefault) {
        FunctionForMapNoDefault<?, ?> that = (FunctionForMapNoDefault<?, ?>) o;
        return map.equals(that.map);
      }
      return false;
    }

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

    @Override
    public String toString() {
      return "Functions.forMap(" + map + ")";
    }

    private static final long serialVersionUID = 0;
  }

  private static class ForMapWithDefault<K, V> implements Function<K, V>, Serializable {
    final Map<K, ? extends V> map;
    @NullableDecl final V defaultValue;

    ForMapWithDefault(Map<K, ? extends V> map, @NullableDecl V defaultValue) {
      this.map = checkNotNull(map);
      this.defaultValue = defaultValue;
    }

    @Override
    public V apply(@NullableDecl K key) {
      V result = map.get(key);
      return (result != null || map.containsKey(key)) ? result : defaultValue;
    }

    @Override
    public boolean equals(@NullableDecl Object o) {
      if (o instanceof ForMapWithDefault) {
        ForMapWithDefault<?, ?> that = (ForMapWithDefault<?, ?>) o;
        return map.equals(that.map) && Objects.equal(defaultValue, that.defaultValue);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(map, defaultValue);
    }

    @Override
    public String toString() {
      // TODO(cpovirk): maybe remove "defaultValue=" to make this look like the method call does
      return "Functions.forMap(" + map + ", defaultValue=" + defaultValue + ")";
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * Returns the composition of two functions. For {@code f: A->B} and {@code g: B->C}, composition
   * is defined as the function h such that {@code h(a) == g(f(a))} for each {@code a}.
   *
   *
Java 8 users: use {@code g.compose(f)} or (probably clearer) {@code f.andThen(g)}
   * instead.
   *
   * @param g the second function to apply
   * @param f the first function to apply
   * @return the composition of {@code f} and {@code g}
   * @see function composition
   */
  public static  Function compose(Function g, Function f) {
    return new FunctionComposition<>(g, f);
  }

  private static class FunctionComposition implements Function, Serializable {
    private final Function g;
    private final Function f;

    public FunctionComposition(Function g, Function f) {
      this.g = checkNotNull(g);
      this.f = checkNotNull(f);
    }

    @Override
    public C apply(@NullableDecl A a) {
      return g.apply(f.apply(a));
    }

    @Override
    public boolean equals(@NullableDecl Object obj) {
      if (obj instanceof FunctionComposition) {
        FunctionComposition<?, ?, ?> that = (FunctionComposition<?, ?, ?>) obj;
        return f.equals(that.f) && g.equals(that.g);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return f.hashCode() ^ g.hashCode();
    }

    @Override
    public String toString() {
      // TODO(cpovirk): maybe make this look like the method call does ("Functions.compose(...)")
      return g + "(" + f + ")";
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * Creates a function that returns the same boolean output as the given predicate for all inputs.
   *
   *
The returned function is consistent with equals (as documented at {@link
   * Function#apply}) if and only if {@code predicate} is itself consistent with equals.
   *
   *
Java 8 users: use the method reference {@code predicate::test} instead.
   */
  public static <T> Function<T, Boolean> forPredicate(Predicate<T> predicate) {
    return new PredicateFunction<T>(predicate);
  }

  /** @see Functions#forPredicate */
  private static class PredicateFunction<T> implements Function<T, Boolean>, Serializable {
    private final Predicate<T> predicate;

    private PredicateFunction(Predicate<T> predicate) {
      this.predicate = checkNotNull(predicate);
    }

    @Override
    public Boolean apply(@NullableDecl T t) {
      return predicate.apply(t);
    }

    @Override
    public boolean equals(@NullableDecl Object obj) {
      if (obj instanceof PredicateFunction) {
        PredicateFunction<?> that = (PredicateFunction<?>) obj;
        return predicate.equals(that.predicate);
      }
      return false;
    }

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

    @Override
    public String toString() {
      return "Functions.forPredicate(" + predicate + ")";
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * Returns a function that ignores its input and always returns {@code value}.
   *
   *
Java 8 users: use the lambda expression {@code o -> value} instead.
   *
   * @param value the constant value for the function to return
   * @return a function that always returns {@code value}
   */
  public static <E> Function<Object, E> constant(@NullableDecl E value) {
    return new ConstantFunction<E>(value);
  }

  private static class ConstantFunction<E> implements Function<Object, E>, Serializable {
    @NullableDecl private final E value;

    public ConstantFunction(@NullableDecl E value) {
      this.value = value;
    }

    @Override
    public E apply(@NullableDecl Object from) {
      return value;
    }

    @Override
    public boolean equals(@NullableDecl Object obj) {
      if (obj instanceof ConstantFunction) {
        ConstantFunction<?> that = (ConstantFunction<?>) obj;
        return Objects.equal(value, that.value);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return (value == null) ? 0 : value.hashCode();
    }

    @Override
    public String toString() {
      return "Functions.constant(" + value + ")";
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * Returns a function that ignores its input and returns the result of {@code supplier.get()}.
   *
   *
Java 8 users: use the lambda expression {@code o -> supplier.get()} instead.
   *
   * @since 10.0
   */
  public static <T> Function<Object, T> forSupplier(Supplier<T> supplier) {
    return new SupplierFunction<T>(supplier);
  }

  /** @see Functions#forSupplier */
  private static class SupplierFunction<T> implements Function<Object, T>, Serializable {

    private final Supplier<T> supplier;

    private SupplierFunction(Supplier<T> supplier) {
      this.supplier = checkNotNull(supplier);
    }

    @Override
    public T apply(@NullableDecl Object input) {
      return supplier.get();
    }

    @Override
    public boolean equals(@NullableDecl Object obj) {
      if (obj instanceof SupplierFunction) {
        SupplierFunction<?> that = (SupplierFunction<?>) obj;
        return this.supplier.equals(that.supplier);
      }
      return false;
    }

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

    @Override
    public String toString() {
      return "Functions.forSupplier(" + supplier + ")";
    }

    private static final long serialVersionUID = 0;
  }
}