aboutsummaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/collect/Ordering.java
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/collect/Ordering.java')
-rw-r--r--guava/src/com/google/common/collect/Ordering.java718
1 files changed, 280 insertions, 438 deletions
diff --git a/guava/src/com/google/common/collect/Ordering.java b/guava/src/com/google/common/collect/Ordering.java
index 9ee9c48..1f0c6e3 100644
--- a/guava/src/com/google/common/collect/Ordering.java
+++ b/guava/src/com/google/common/collect/Ordering.java
@@ -19,13 +19,12 @@ 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.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
@@ -35,15 +34,13 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.SortedMap;
import java.util.SortedSet;
-import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
/**
- * A comparator, with additional methods to support common operations. This is
- * an "enriched" version of {@code Comparator}, in the same sense that {@link
- * FluentIterable} is an enriched {@link Iterable}). For example: <pre> {@code
+ * A comparator with added methods to support common functions. For example:
+ * <pre> {@code
*
* if (Ordering.from(comparator).reverse().isOrdered(list)) { ... }}</pre>
*
@@ -62,17 +59,13 @@ import javax.annotation.Nullable;
* are. For example, if {@code ordering} and {@code function} can themselves be
* serialized, then {@code ordering.onResultOf(function)} can as well.
*
- * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/OrderingExplained">
- * {@code Ordering}</a>.
- *
* @author Jesse Wilson
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class Ordering<T> implements Comparator<T> {
- // Natural order
+ // Static factories
/**
* Returns a serializable ordering that uses the natural order of the values.
@@ -89,17 +82,13 @@ public abstract class Ordering<T> implements Comparator<T> {
return (Ordering<C>) NaturalOrdering.INSTANCE;
}
- // Static factories
-
/**
- * Returns an ordering based on an <i>existing</i> comparator instance. Note
- * that there's no need to create a <i>new</i> comparator just to pass it in
- * here; simply subclass {@code Ordering} and implement its {@code compareTo}
- * method directly instead.
+ * Returns an ordering for a pre-existing {@code comparator}. Note
+ * that if the comparator is not pre-existing, and you don't require
+ * serialization, you can subclass {@code Ordering} and implement its
+ * {@link #compare(Object, Object) compare} method instead.
*
* @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) {
@@ -173,48 +162,23 @@ public abstract class Ordering<T> implements Comparator<T> {
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 <i>stable</i> 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.
- *
- * <p>Example: <pre> {@code
- *
- * Ordering.allEqual().nullsLast().sortedCopy(
- * asList(t, null, e, s, null, t, null))}</pre>
- *
- * Assuming {@code t}, {@code e} and {@code s} are non-null, this returns
- * {@code [t, e, s, t, null, null, null]} regardlesss of the true comparison
- * order of those three values (which might not even implement {@link
- * Comparable} at all).
- *
- * <p><b>Warning:</b> by definition, this comparator is not <i>consistent with
- * equals</i> (as defined {@linkplain Comparator here}). Avoid its use in
- * APIs, such as {@link TreeSet#TreeSet(Comparator)}, where such consistency
- * is expected.
- *
- * <p>The returned comparator is serializable.
+ * 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.
*/
- @GwtCompatible(serializable = true)
- @SuppressWarnings("unchecked")
- public static Ordering<Object> allEqual() {
- return AllEqualOrdering.INSTANCE;
- }
+ // TODO(kevinb): make this public, document it right
+ @VisibleForTesting
+ static class IncomparableValueException extends ClassCastException {
+ final Object value;
- /**
- * 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.
- *
- * <p>The comparator is serializable.
- */
- @GwtCompatible(serializable = true)
- public static Ordering<Object> usingToString() {
- return UsingToStringOrdering.INSTANCE;
+ IncomparableValueException(Object value) {
+ super("Cannot compare value: " + value);
+ this.value = value;
+ }
+
+ private static final long serialVersionUID = 0;
}
/**
@@ -256,10 +220,6 @@ public abstract class Ordering<T> implements Comparator<T> {
@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);
@@ -292,62 +252,46 @@ public abstract class Ordering<T> implements Comparator<T> {
}
}
- // 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)}.
+ * 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.
+ *
+ * <p>The comparator is serializable.
*/
- // 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);
+ public static Ordering<Object> usingToString() {
+ return UsingToStringOrdering.INSTANCE;
}
/**
- * Returns an ordering that treats {@code null} as less than all other values
- * and uses {@code this} to compare non-null values.
+ * 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.
+ *
+ * <p>The returned ordering is equivalent to that produced using {@code
+ * Ordering.from(comp1).compound(comp2).compound(comp3) . . .}.
+ *
+ * <p><b>Warning:</b> Supplying an argument with undefined iteration order,
+ * such as a {@link HashSet}, will produce non-deterministic results.
+ *
+ * @param comparators the comparators to try in order
*/
- // 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);
+ public static <T> Ordering<T> compound(
+ Iterable<? extends Comparator<? super T>> comparators) {
+ return new CompoundOrdering<T>(comparators);
}
/**
- * Returns an ordering that treats {@code null} as greater than all other
- * values and uses this ordering to compare non-null values.
+ * Constructs a new instance of this class (only invokable by the subclass
+ * constructor, typically implicit).
*/
- // 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);
- }
+ protected Ordering() {}
- /**
- * 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: <pre> {@code
- *
- * Ordering.from(String.CASE_INSENSITIVE_ORDER)
- * .onResultOf(Functions.toStringFunction())}</pre>
- */
- @GwtCompatible(serializable = true)
- public <F> Ordering<F> onResultOf(Function<F, ? extends T> function) {
- return new ByFunctionOrdering<F, T>(function, this);
- }
+ // Non-static factories
/**
* Returns an ordering which first uses the ordering {@code this}, but which
@@ -367,24 +311,28 @@ public abstract class Ordering<T> implements Comparator<T> {
}
/**
- * 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.
- *
- * <p>The returned ordering is equivalent to that produced using {@code
- * Ordering.from(comp1).compound(comp2).compound(comp3) . . .}.
- *
- * <p><b>Warning:</b> Supplying an argument with undefined iteration order,
- * such as a {@link HashSet}, will produce non-deterministic results.
+ * Returns the reverse of this ordering; the {@code Ordering} equivalent to
+ * {@link Collections#reverseOrder(Comparator)}.
+ */
+ // 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 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: <pre> {@code
*
- * @param comparators the comparators to try in order
+ * Ordering.from(String.CASE_INSENSITIVE_ORDER)
+ * .onResultOf(Functions.toStringFunction())}</pre>
*/
@GwtCompatible(serializable = true)
- public static <T> Ordering<T> compound(
- Iterable<? extends Comparator<? super T>> comparators) {
- return new CompoundOrdering<T>(comparators);
+ public <F> Ordering<F> onResultOf(Function<F, ? extends T> function) {
+ return new ByFunctionOrdering<F, T>(function, this);
}
/**
@@ -416,162 +364,32 @@ public abstract class Ordering<T> implements Comparator<T> {
return new LexicographicalOrdering<S>(this);
}
- // Regular instance methods
-
- // Override to add @Nullable
- @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}.
- *
- * @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 <i>mutually
- * comparable</i> 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.
- *
- * @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 <i>mutually
- * comparable</i> 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.
- *
- * <p><b>Implementation note:</b> this method is invoked by the default
- * implementations of the other {@code min} overloads, so overriding it will
- * affect their behavior.
- *
- * @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 <i>mutually
- * comparable</i> 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.
- *
- * @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 <i>mutually
- * comparable</i> 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}.
- *
- * @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 <i>mutually
- * comparable</i> 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.
- *
- * @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 <i>mutually
- * comparable</i> under this ordering.
+ * Returns an ordering that treats {@code null} as less than all other values
+ * and uses {@code this} to compare non-null values.
*/
- public <E extends T> E max(Iterable<E> iterable) {
- return max(iterable.iterator());
+ // 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 the greater of the two values according to this ordering. If the
- * values compare as 0, the first is returned.
- *
- * <p><b>Implementation note:</b> this method is invoked by the default
- * implementations of the other {@code max} overloads, so overriding it will
- * affect their behavior.
- *
- * @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 <i>mutually
- * comparable</i> under this ordering.
+ * Returns an ordering that treats {@code null} as greater than all other
+ * values and uses this ordering to compare non-null values.
*/
- public <E extends T> E max(@Nullable E a, @Nullable E b) {
- return (compare(a, b) >= 0) ? a : b;
+ // 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 the greatest of the specified values according to this ordering. If
- * there are multiple greatest values, the first of those 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 <i>mutually
- * comparable</i> 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);
- }
+ // Regular instance methods
- return maxSoFar;
- }
+ // Override to add @Nullable
+ @Override public abstract int compare(@Nullable T left, @Nullable T right);
/**
* Returns the {@code k} least elements of the given iterable according to
@@ -587,130 +405,64 @@ public abstract class Ordering<T> implements Comparator<T> {
* @throws IllegalArgumentException if {@code k} is negative
* @since 8.0
*/
+ @Beta
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 = ObjectArrays.arraysCopyOf(array, k);
- }
- return Collections.unmodifiableList(Arrays.asList(array));
- }
+ checkArgument(k >= 0, "%d is negative", k);
+
+ // values is not an E[], but we use it as such for readability. Hack.
+ @SuppressWarnings("unchecked")
+ E[] values = (E[]) Iterables.toArray(iterable);
+
+ // TODO(nshupe): also sort whole list if k is *near* values.length?
+ // TODO(kevinb): benchmark this impl against hand-coded heap
+ E[] resultArray;
+ if (values.length <= k) {
+ Arrays.sort(values, this);
+ resultArray = values;
+ } else {
+ quicksortLeastK(values, 0, values.length - 1, k);
+
+ // this is not an E[], but we use it as such for readability. Hack.
+ @SuppressWarnings("unchecked")
+ E[] tmp = (E[]) new Object[k];
+ resultArray = tmp;
+ System.arraycopy(values, 0, resultArray, 0, k);
}
- return leastOf(iterable.iterator(), k);
+
+ return Collections.unmodifiableList(Arrays.asList(resultArray));
}
/**
- * 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
+ * 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.
*
* <p>The implementation does not necessarily use a <i>stable</i> sorting
* algorithm; when multiple elements are equivalent, it is undefined which
* will come first.
*
- * @return an immutable {@code RandomAccess} list of the {@code k} least
- * elements in ascending order
+ * @return an immutable {@code RandomAccess} list of the {@code k} greatest
+ * elements in <i>descending order</i>
* @throws IllegalArgumentException if {@code k} is negative
- * @since 14.0
+ * @since 8.0
*/
- public <E extends T> List<E> leastOf(Iterator<E> elements, int k) {
- checkNotNull(elements);
- checkArgument(k >= 0, "k (%s) must be nonnegative", k);
-
- if (k == 0 || !elements.hasNext()) {
- return ImmutableList.of();
- } else if (k >= Integer.MAX_VALUE / 2) {
- // k is really large; just do a straightforward sorted-copy-and-sublist
- ArrayList<E> list = Lists.newArrayList(elements);
- Collections.sort(list, this);
- if (list.size() > k) {
- list.subList(k, list.size()).clear();
- }
- list.trimToSize();
- return Collections.unmodifiableList(list);
- }
-
- /*
- * Our goal is an O(n) algorithm using only one pass and O(k) additional
- * memory.
- *
- * We use the following algorithm: maintain a buffer of size 2*k. Every time
- * the buffer gets full, find the median and partition around it, keeping
- * only the lowest k elements. This requires n/k find-median-and-partition
- * steps, each of which take O(k) time with a traditional quickselect.
- *
- * After sorting the output, the whole algorithm is O(n + k log k). It
- * degrades gracefully for worst-case input (descending order), performs
- * competitively or wins outright for randomly ordered input, and doesn't
- * require the whole collection to fit into memory.
- */
- int bufferCap = k * 2;
- @SuppressWarnings("unchecked") // we'll only put E's in
- E[] buffer = (E[]) new Object[bufferCap];
- E threshold = elements.next();
- buffer[0] = threshold;
- int bufferSize = 1;
- // threshold is the kth smallest element seen so far. Once bufferSize >= k,
- // anything larger than threshold can be ignored immediately.
-
- while (bufferSize < k && elements.hasNext()) {
- E e = elements.next();
- buffer[bufferSize++] = e;
- threshold = max(threshold, e);
- }
-
- while (elements.hasNext()) {
- E e = elements.next();
- if (compare(e, threshold) >= 0) {
- continue;
- }
-
- buffer[bufferSize++] = e;
- if (bufferSize == bufferCap) {
- // We apply the quickselect algorithm to partition about the median,
- // and then ignore the last k elements.
- int left = 0;
- int right = bufferCap - 1;
-
- int minThresholdPosition = 0;
- // The leftmost position at which the greatest of the k lower elements
- // -- the new value of threshold -- might be found.
-
- while (left < right) {
- int pivotIndex = (left + right + 1) >>> 1;
- int pivotNewIndex = partition(buffer, left, right, pivotIndex);
- if (pivotNewIndex > k) {
- right = pivotNewIndex - 1;
- } else if (pivotNewIndex < k) {
- left = Math.max(pivotNewIndex, left + 1);
- minThresholdPosition = pivotNewIndex;
- } else {
- break;
- }
- }
- bufferSize = k;
+ @Beta
+ 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);
+ }
- threshold = buffer[minThresholdPosition];
- for (int i = minThresholdPosition + 1; i < bufferSize; i++) {
- threshold = max(threshold, buffer[i]);
- }
+ private <E extends T> void quicksortLeastK(
+ E[] values, int left, int right, int k) {
+ if (right > left) {
+ int pivotIndex = (left + right) >>> 1; // left + ((right - left) / 2)
+ int pivotNewIndex = partition(values, left, right, pivotIndex);
+ quicksortLeastK(values, left, pivotNewIndex - 1, k);
+ if (pivotNewIndex < k) {
+ quicksortLeastK(values, pivotNewIndex + 1, right, k);
}
}
-
- Arrays.sort(buffer, 0, bufferSize, this);
-
- bufferSize = Math.min(bufferSize, k);
- return Collections.unmodifiableList(
- Arrays.asList(ObjectArrays.arraysCopyOf(buffer, bufferSize)));
- // We can't use ImmutableList; we have to be null-friendly!
}
private <E extends T> int partition(
@@ -732,41 +484,15 @@ public abstract class Ordering<T> implements Comparator<T> {
}
/**
- * 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.
- *
- * <p>The implementation does not necessarily use a <i>stable</i> sorting
- * algorithm; when multiple elements are equivalent, it is undefined which
- * will come first.
- *
- * @return an immutable {@code RandomAccess} list of the {@code k} greatest
- * elements in <i>descending order</i>
- * @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.
- *
- * <p>The implementation does not necessarily use a <i>stable</i> sorting
- * algorithm; when multiple elements are equivalent, it is undefined which
- * will come first.
+ * {@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.
*
- * @return an immutable {@code RandomAccess} list of the {@code k} greatest
- * elements in <i>descending order</i>
- * @throws IllegalArgumentException if {@code k} is negative
- * @since 14.0
+ * @param sortedList the list to be searched
+ * @param key the key to be searched for
*/
- public <E extends T> List<E> greatestOf(Iterator<E> iterator, int k) {
- return reverse().leastOf(iterator, k);
+ public int binarySearch(List<? extends T> sortedList, @Nullable T key) {
+ return Collections.binarySearch(sortedList, key, this);
}
/**
@@ -783,10 +509,9 @@ public abstract class Ordering<T> implements Comparator<T> {
* @return a new list containing the given elements in sorted order
*/
public <E extends T> List<E> sortedCopy(Iterable<E> iterable) {
- @SuppressWarnings("unchecked") // does not escape, and contains only E's
- E[] array = (E[]) Iterables.toArray(iterable);
- Arrays.sort(array, this);
- return Lists.newArrayList(Arrays.asList(array));
+ List<E> list = Lists.newArrayList(iterable);
+ Collections.sort(list, this);
+ return list;
}
/**
@@ -806,13 +531,7 @@ public abstract class Ordering<T> implements Comparator<T> {
*/
public <E extends T> ImmutableList<E> immutableSortedCopy(
Iterable<E> iterable) {
- @SuppressWarnings("unchecked") // we'll only ever have E's in here
- E[] elements = (E[]) Iterables.toArray(iterable);
- for (E e : elements) {
- checkNotNull(e);
- }
- Arrays.sort(elements, this);
- return ImmutableList.asImmutableList(elements);
+ return ImmutableList.copyOf(sortedCopy(iterable));
}
/**
@@ -858,34 +577,157 @@ public abstract class Ordering<T> implements Comparator<T> {
}
/**
- * {@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.
+ * 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}.
*
- * @param sortedList the list to be searched
- * @param key the key to be searched for
+ * @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 <i>mutually
+ * comparable</i> under this ordering.
+ *
+ * @since 11.0
*/
- public int binarySearch(List<? extends T> sortedList, @Nullable T key) {
- return Collections.binarySearch(sortedList, key, this);
+ @Beta
+ 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;
}
/**
- * 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.
+ * Returns the greatest of the specified values according to this ordering. If
+ * there are multiple greatest values, the first of those 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 <i>mutually
+ * comparable</i> under this ordering.
*/
- // TODO(kevinb): make this public, document it right
- @VisibleForTesting
- static class IncomparableValueException extends ClassCastException {
- final Object value;
+ public <E extends T> E max(Iterable<E> iterable) {
+ return max(iterable.iterator());
+ }
- IncomparableValueException(Object value) {
- super("Cannot compare value: " + value);
- this.value = value;
+ /**
+ * Returns the greatest of the specified values according to this ordering. If
+ * there are multiple greatest values, the first of those 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 <i>mutually
+ * comparable</i> 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);
}
- private static final long serialVersionUID = 0;
+ return maxSoFar;
+ }
+
+ /**
+ * Returns the greater of the two values according to this ordering. If the
+ * values compare as 0, the first is returned.
+ *
+ * <p><b>Implementation note:</b> this method is invoked by the default
+ * implementations of the other {@code max} overloads, so overriding it will
+ * affect their behavior.
+ *
+ * @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 <i>mutually
+ * comparable</i> under this ordering.
+ */
+ public <E extends T> E max(@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. The
+ * iterator will be left exhausted: its {@code hasNext()} method will return
+ * {@code false}.
+ *
+ * @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 <i>mutually
+ * comparable</i> under this ordering.
+ *
+ * @since 11.0
+ */
+ @Beta
+ 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.
+ *
+ * @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 <i>mutually
+ * comparable</i> under this ordering.
+ */
+ public <E extends T> E min(Iterable<E> iterable) {
+ return min(iterable.iterator());
+ }
+
+ /**
+ * Returns the least of the specified values according to this ordering. If
+ * there are multiple least values, the first of those 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 <i>mutually
+ * comparable</i> 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 lesser of the two values according to this ordering. If the
+ * values compare as 0, the first is returned.
+ *
+ * <p><b>Implementation note:</b> this method is invoked by the default
+ * implementations of the other {@code min} overloads, so overriding it will
+ * affect their behavior.
+ *
+ * @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 <i>mutually
+ * comparable</i> under this ordering.
+ */
+ public <E extends T> E min(@Nullable E a, @Nullable E b) {
+ return compare(a, b) <= 0 ? a : b;
}
// Never make these public