src/share/classes/java/util/Comparator.java

Print this page
rev 7485 : 8009736: Comparator API cleanup
Reviewed-by:
Contributed-by: henry.jen@oracle.com

@@ -23,14 +23,16 @@
  * questions.
  */
 
 package java.util;
 
+import java.io.Serializable;
 import java.util.function.Function;
 import java.util.function.ToIntFunction;
 import java.util.function.ToLongFunction;
 import java.util.function.ToDoubleFunction;
+import java.util.Comparators;
 
 /**
  * A comparison function, which imposes a <i>total ordering</i> on some
  * collection of objects.  Comparators can be passed to a sort method (such
  * as {@link Collections#sort(List,Comparator) Collections.sort} or {@link

@@ -177,86 +179,353 @@
      *
      * @return A comparator that imposes the reverse ordering of this
      *         comparator.
      * @since 1.8
      */
-    default Comparator<T> reverseOrder() {
+    default Comparator<T> reversed() {
         return Collections.reverseOrder(this);
     }
 
     /**
      * Constructs a lexicographic order comparator with another comparator.
-     * For example, a {@code Comparator<Person> byLastName} can be composed
-     * with another {@code Comparator<Person> byFirstName}, then {@code
-     * byLastName.thenComparing(byFirstName)} creates a {@code
-     * Comparator<Person>} which sorts by last name, and for equal last names
-     * sorts by first name.
+     * If this {@code Comparator} considers two elements equal, i.e.
+     * {@code compare(a, b) == 0}, {@code other} is used to determine the order.
      *
-     * @param other the other comparator used when equals on this.
+     * <p>The returned comparator is serializable if the specified comparator
+     * is also serializable.
+     *
+     * @apiNote
+     * To sort a collection of {@code String} based on the length and then
+     * case-insensitive natural ordering, the comparator can be construcred
+     * using following code,
+     *
+     * <pre>{@code
+     *     Comparator<String> cmp = Comparator.comparing(String::length)
+     *             .thenComparing(String.CASE_INSENSITIVE_ORDER);
+     * }</pre>
+     *
+     * @param  other the other comparator to be used when this comparator
+     *         compares two objects that are equal.
+     * @return A lexicographic order comparator composed of this and then the
+     *         other comparator
      * @throws NullPointerException if the argument is null.
      * @since 1.8
      */
     default Comparator<T> thenComparing(Comparator<? super T> other) {
-        return Comparators.compose(this, other);
+        Objects.requireNonNull(other);
+        return (Comparator<T> & Serializable) (c1, c2) -> {
+            int res = compare(c1, c2);
+            return (res != 0) ? res : other.compare(c1, c2);
+        };
     }
 
     /**
      * Constructs a lexicographic order comparator with a function that
-     * extracts a {@code Comparable} key.  This default implementation calls
-     * {@code thenComparing(this, Comparators.comparing(keyExtractor))}.
+     * extracts a key to be compared with the given {@code Comparator}.
+     *
+     * @implSpec This default implementation calls {@code
+     *           thenComparing(comparing(keyExtractor, cmp))}.
      *
-     * @param <U> the {@link Comparable} type for comparison
-     * @param keyExtractor the function used to extract the {@link Comparable} sort key
+     * @param  <U>  The type of the sort key
+     * @param  keyExtractor the function used to extract the sort key
+     * @param  keyComparator the {@code Comparator} used to compare the sort key
+     * @return A lexicographic order comparator composed of this and then the
+     *         key comparator.
      * @throws NullPointerException if the argument is null.
-     * @see Comparators#comparing(Function)
+     * @see #comparing(Function, Comparator)
      * @see #thenComparing(Comparator)
      * @since 1.8
      */
-    default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor) {
-        return thenComparing(Comparators.comparing(keyExtractor));
+    default <U extends Comparable<? super U>> Comparator<T> thenComparing(
+            Function<? super T, ? extends U> keyExtractor,
+            Comparator<? super U> keyComparator)
+    {
+        return thenComparing(comparing(keyExtractor, keyComparator));
     }
 
     /**
      * Constructs a lexicographic order comparator with a function that
-     * extracts a {@code int} value.  This default implementation calls {@code
-     * thenComparing(this, Comparators.comparing(keyExtractor))}.
+     * extracts a {@code Comparable} sort key.
+     *
+     * @implSpec This default implementation calls {@code
+     *           thenComparing(comparing(keyExtractor))}.
      *
-     * @param keyExtractor the function used to extract the integer value
+     * @param  <U>  The type of the {@link Comparable} sort key
+     * @param  keyExtractor the function used to extract the {@link
+     *         Comparable} sort key
+     * @return A lexicographic order comparator composed of this and then the
+     *         {@link Comparable} sort key.
      * @throws NullPointerException if the argument is null.
-     * @see Comparators#comparing(ToIntFunction)
+     * @see #comparing(Function)
+     * @see #thenComparing(Comparator)
+     * @since 1.8
+     */
+    default <U extends Comparable<? super U>> Comparator<T> thenComparing(
+            Function<? super T, ? extends U> keyExtractor)
+    {
+        return thenComparing(comparing(keyExtractor));
+    }
+
+    /**
+     * Constructs a lexicographic order comparator with a function that
+     * extracts a {@code int} sort key.
+     *
+     * @implSpec This default implementation calls {@code
+     *           thenComparing(comparing(keyExtractor))}.
+     *
+     * @param  keyExtractor the function used to extract the integer sort key
+     * @return A lexicographic order comparator composed of this and then the
+     *         {@code int} sort key
+     * @throws NullPointerException if the argument is null.
+     * @see #comparing(ToIntFunction)
      * @see #thenComparing(Comparator)
      * @since 1.8
      */
     default Comparator<T> thenComparing(ToIntFunction<? super T> keyExtractor) {
-        return thenComparing(Comparators.comparing(keyExtractor));
+        return thenComparing(comparing(keyExtractor));
     }
 
     /**
      * Constructs a lexicographic order comparator with a function that
-     * extracts a {@code long} value.  This default implementation calls
-     * {@code thenComparing(this, Comparators.comparing(keyExtractor))}.
+     * extracts a {@code long} sort key.
      *
-     * @param keyExtractor the function used to extract the long value
+     * @implSpec This default implementation calls {@code
+     *           thenComparing(comparing(keyExtractor))}.
+     *
+     * @param  keyExtractor the function used to extract the long sort key
+     * @return A lexicographic order comparator composed of this and then the
+     *         {@code long} sort key
      * @throws NullPointerException if the argument is null.
-     * @see Comparators#comparing(ToLongFunction)
+     * @see #comparing(ToLongFunction)
      * @see #thenComparing(Comparator)
      * @since 1.8
      */
     default Comparator<T> thenComparing(ToLongFunction<? super T> keyExtractor) {
-        return thenComparing(Comparators.comparing(keyExtractor));
+        return thenComparing(comparing(keyExtractor));
     }
 
     /**
      * Constructs a lexicographic order comparator with a function that
-     * extracts a {@code double} value.  This default implementation calls
-     * {@code thenComparing(this, Comparators.comparing(keyExtractor))}.
+     * extracts a {@code double} sort key.
+     *
+     * @implSpec This default implementation calls {@code
+     *           thenComparing(comparing(keyExtractor))}.
      *
-     * @param keyExtractor the function used to extract the double value
+     * @param  keyExtractor the function used to extract the double sort key
+     * @return A lexicographic order comparator composed of this and then the
+     *         {@code double} sort key
      * @throws NullPointerException if the argument is null.
-     * @see Comparators#comparing(ToDoubleFunction)
+     * @see #comparing(ToDoubleFunction)
      * @see #thenComparing(Comparator)
      * @since 1.8
      */
     default Comparator<T> thenComparing(ToDoubleFunction<? super T> keyExtractor) {
-        return thenComparing(Comparators.comparing(keyExtractor));
+        return thenComparing(comparing(keyExtractor));
+    }
+
+    /**
+     * Returns a comparator that imposes the reverse of the <em>natural
+     * ordering</em>.
+     *
+     * <p>The returned comparator is serializable and throws {@link
+     * NullPointerException} when comparing {@code null}.
+     *
+     * @param  <T> The {@link Comparable} type of element to be compared
+     * @return A comparator that imposes the reverse of the <i>natural
+     *         ordering</i> on a collection of objects that implement
+     *         the {@link Comparable} interface.
+     * @see Comparable
+     * @since 1.8
+     */
+    public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
+        return Collections.reverseOrder();
+    }
+
+    /**
+     * Returns a comparator that compares {@link Comparable} type in natural
+     * order.
+     *
+     * <p>The returned comparator is serializable and throws {@link
+     * NullPointerException} when comparing {@code null}.
+     *
+     * @param  <T> The {@link Comparable} type of element to be compared
+     * @return A comparator that imposes the <i>natural ordering</i> on a
+     *         collection of objects that implement the {@link Comparable}
+     *         interface.
+     * @see Comparable
+     * @since 1.8
+     */
+    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
+        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
+    }
+
+    /**
+     * Returns a null-friendly comparator that considers {@code null} to be
+     * less than non-null. When both are {@code null}, they are considered
+     * equal. If both are non-null, the specified {@code Comparator} is used
+     * to determine the order. If the specified comparator is {@code null},
+     * then the returned comparator considers all non-null values to be equal.
+     *
+     * <p>The returned comparator is serializable if the specified comparator
+     * is serializable.
+     *
+     * @param  <T> the type of the elements to be compared
+     * @param  comparator A {@code Comparator} for comparing non-null values
+     * @return A comparator that considers {@code null} to be less than non-null.
+     * @since 1.8
+     */
+    public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
+        return new Comparators.NullComparator(true, comparator);
+    }
+
+    /**
+     * Returns a null-friendly comparator that considers {@code null} to be
+     * greater than non-null. When both are {@code null}, they are considered
+     * equal. If both are non-null, the specified {@code Comparator} is used
+     * to determine the order. If the specified comparator is {@code null},
+     * then the returned comparator considers all non-null values to be equal.
+     *
+     * <p>The returned comparator is serializable if the specified comparator
+     * is serializable.
+     *
+     * @param  <T> the type of the elements to be compared
+     * @param  comparator A {@code Comparator} for comparing non-null values
+     * @return A comparator that considers {@code null} to be greater than non-null.
+     * @since 1.8
+     */
+    public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
+        return new Comparators.NullComparator(false, comparator);
+    }
+
+    /**
+     * Accepts a function that extracts a sort key from a type {@code T}, and
+     * returns a {@code Comparator<T>} that compares by that sort key using
+     * the specified {@link Comparator}.
+      *
+     * <p>The returned comparator is serializable if the specified function
+     * and comparator are both serializable.
+     *
+     * @apiNote
+     * To obtain a {@code Comparator} that compares {@code Person} objects by their last name
+     * ignoring case differences,
+     *
+     * <pre>{@code
+     *     Comparator<People> cmp = Comparator.comparing(
+     *             Person::getLastName,
+     *             String.CASE_INSENSITIVE_ORDER);
+     * }</pre>
+     *
+     * @param  <T> The type of element to be compared
+     * @param  <U> The type of the sort key
+     * @param  keyExtractor the function used to extract the sort key
+     * @param  keyComparator the {@code Comparator} used to compare the sort key
+     * @return A comparator that compares by an extracted key using the
+     *         specified {@code Comparator}
+     * @throws NullPointerException if the argument is null
+     * @since 1.8
+     */
+    public static <T, U> Comparator<T> comparing(
+            Function<? super T, ? extends U> keyExtractor,
+            Comparator<? super U> keyComparator)
+    {
+        Objects.requireNonNull(keyExtractor);
+        Objects.requireNonNull(keyComparator);
+        return (Comparator<T> & Serializable)
+            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
+                                              keyExtractor.apply(c2));
+    }
+
+    /**
+     * Accepts a function that extracts a {@link java.lang.Comparable
+     * Comparable} sort key from a type {@code T}, and returns a {@code
+     * Comparator<T>} that compares by that sort key.
+     *
+     * <p>The returned comparator is serializable if the specified function
+     * is also serializable.
+     *
+     * @apiNote
+     * To obtain a {@code Comparator} that compares {@code Person} objects by their last
+     * name,
+     *
+     * <pre>{@code
+     *     Comparator<People> byLastName = Comparator.comparing(Person::getLastName);
+     * }</pre>
+     *
+     * @param  <T> The type of element to be compared
+     * @param  <U> The type of the {@code Comparable} sort key
+     * @param  keyExtractor the function used to extract the {@link
+     *         Comparable} sort key
+     * @return A comparator that compares by an extracted key
+     * @throws NullPointerException if the argument is null
+     * @since 1.8
+     */
+    public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
+            Function<? super T, ? extends U> keyExtractor)
+    {
+        Objects.requireNonNull(keyExtractor);
+        return (Comparator<T> & Serializable)
+            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
+    }
+
+    /**
+     * Accepts a function that extracts an {@code int} sort key from a type
+     * {@code T}, and returns a {@code Comparator<T>} that compares by that
+     * sort key.
+     *
+     * <p>The returned comparator is serializable if the specified function
+     * is also serializable.
+     *
+     * @param  <T> The type of element to be compared
+     * @param  keyExtractor the function used to extract the integer sort key
+     * @return A comparator that compares by an extracted key
+     * @see #comparing(Function)
+     * @throws NullPointerException if the argument is null
+     * @since 1.8
+     */
+    public static <T> Comparator<T> comparing(ToIntFunction<? super T> keyExtractor) {
+        Objects.requireNonNull(keyExtractor);
+        return (Comparator<T> & Serializable)
+            (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
+    }
+
+    /**
+     * Accepts a function that extracts a {@code long} sort key from a type
+     * {@code T}, and returns a {@code Comparator<T>} that compares by that
+     * sort key.
+     *
+     * <p>The returned comparator is serializable if the specified function is
+     * also serializable.
+     *
+     * @param  <T> The type of element to be compared
+     * @param  keyExtractor the function used to extract the long sort key
+     * @return A comparator that compares by an extracted key
+     * @see #comparing(Function)
+     * @throws NullPointerException if the argument is null
+     * @since 1.8
+     */
+    public static <T> Comparator<T> comparing(ToLongFunction<? super T> keyExtractor) {
+        Objects.requireNonNull(keyExtractor);
+        return (Comparator<T> & Serializable)
+            (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
+    }
+
+    /**
+     * Accepts a function that extracts a {@code double} sort key from a type
+     * {@code T}, and returns a {@code Comparator<T>} that compares by that
+     * sort key.
+     *
+     * <p>The returned comparator is serializable if the specified function
+     * is also serializable.
+     *
+     * @param  <T> The type of element to be compared
+     * @param  keyExtractor the function used to extract the double sort key
+     * @return A comparator that compares by an extracted key
+     * @see #comparing(Function)
+     * @throws NullPointerException if the argument is null
+     * @since 1.8
+     */
+    public static<T> Comparator<T> comparing(ToDoubleFunction<? super T> keyExtractor) {
+        Objects.requireNonNull(keyExtractor);
+        return (Comparator<T> & Serializable)
+            (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
     }
 }