OpenJDK / lambda / lambda / jdk
changeset 7596:fb7b7275d220
8009736: Comparator to allow narrowing type on combinator APIs
Reviewed-by:
Summary: Allow to narrow return type, add javadoc return tag
Allow key extract not limited to Comparable, but use a Comparator of key type.
author | henryjen |
---|---|
date | Fri, 08 Mar 2013 21:54:17 -0800 |
parents | 79a9684a5542 |
children | c436657091ee |
files | src/share/classes/java/util/Comparator.java src/share/classes/java/util/Comparators.java |
diffstat | 2 files changed, 123 insertions(+), 93 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/java/util/Comparator.java Fri Mar 08 16:02:27 2013 -0800 +++ b/src/share/classes/java/util/Comparator.java Fri Mar 08 21:54:17 2013 -0800 @@ -25,6 +25,7 @@ package java.util; +import java.io.Serializable; import java.util.function.Function; import java.util.function.ToIntFunction; import java.util.function.ToLongFunction; @@ -179,8 +180,8 @@ * comparator. * @since 1.8 */ - default Comparator<T> reverseOrder() { - return Collections.reverseOrder(this); + default <S extends T> Comparator<S> reverseOrder() { + return (Comparator<S>) Collections.reverseOrder(this); } /** @@ -191,12 +192,39 @@ * Comparator<Person>} which sorts by last name, and for equal last names * sorts by first name. * - * @param other the other comparator used when equals on this. + * @param <S> The type of elements compared by the returned comparator. + * @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); + default <S extends T> Comparator<S> thenComparing(Comparator<? super T> other) { + return (Comparator<S> & 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 key to be compared with the given {@code Comparator}. This + * default implementation calls {@code thenComparing(this, + * Comparators.comparing(keyExtractor, cmp))}. + * + * @param <S> The type of elements compared by the returned comparator. + * @param <U> The type of the key for comparison + * @param keyExtractor the function used to extract 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, Comparator) + * @see #thenComparing(Comparator) + * @since 1.8 + */ + default <S extends T, U> Comparator<S> thenComparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> cmp) { + return thenComparing(Comparators.comparing(keyExtractor, cmp)); } /** @@ -204,14 +232,17 @@ * extracts a {@code Comparable} key. This default implementation calls * {@code thenComparing(this, Comparators.comparing(keyExtractor))}. * - * @param <U> the {@link Comparable} type for comparison - * @param keyExtractor the function used to extract the {@link Comparable} sort key + * @param <S> The type of elements compared by the returned comparator. + * @param <U> The {@link Comparable} type for comparison + * @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} key. * @throws NullPointerException if the argument is null. * @see Comparators#comparing(Function) * @see #thenComparing(Comparator) * @since 1.8 */ - default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor) { + default <S extends T, U extends Comparable<? super U>> Comparator<S> thenComparing(Function<? super T, ? extends U> keyExtractor) { return thenComparing(Comparators.comparing(keyExtractor)); } @@ -220,13 +251,16 @@ * extracts a {@code int} value. This default implementation calls {@code * thenComparing(this, Comparators.comparing(keyExtractor))}. * - * @param keyExtractor the function used to extract the integer value + * @param <S> The type of elements compared by the returned comparator. + * @param keyExtractor the function used to extract the integer value + * @return A lexicographic order comparator composed of this and then the + * {@code int} value * @throws NullPointerException if the argument is null. * @see Comparators#comparing(ToIntFunction) * @see #thenComparing(Comparator) * @since 1.8 */ - default Comparator<T> thenComparing(ToIntFunction<? super T> keyExtractor) { + default <S extends T> Comparator<S> thenComparing(ToIntFunction<? super T> keyExtractor) { return thenComparing(Comparators.comparing(keyExtractor)); } @@ -235,13 +269,16 @@ * extracts a {@code long} value. This default implementation calls * {@code thenComparing(this, Comparators.comparing(keyExtractor))}. * - * @param keyExtractor the function used to extract the long value + * @param <S> The type of elements compared by the returned comparator. + * @param keyExtractor the function used to extract the long value + * @return A lexicographic order comparator composed of this and then the + * {@code long} value * @throws NullPointerException if the argument is null. * @see Comparators#comparing(ToLongFunction) * @see #thenComparing(Comparator) * @since 1.8 */ - default Comparator<T> thenComparing(ToLongFunction<? super T> keyExtractor) { + default <S extends T> Comparator<S> thenComparing(ToLongFunction<? super T> keyExtractor) { return thenComparing(Comparators.comparing(keyExtractor)); } @@ -250,13 +287,16 @@ * extracts a {@code double} value. This default implementation calls * {@code thenComparing(this, Comparators.comparing(keyExtractor))}. * - * @param keyExtractor the function used to extract the double value + * @param <S> The type of elements compared by the returned comparator. + * @param keyExtractor the function used to extract the double value + * @return A lexicographic order comparator composed of this and then the + * {@code double} value * @throws NullPointerException if the argument is null. * @see Comparators#comparing(ToDoubleFunction) * @see #thenComparing(Comparator) * @since 1.8 */ - default Comparator<T> thenComparing(ToDoubleFunction<? super T> keyExtractor) { + default <S extends T> Comparator<S> thenComparing(ToDoubleFunction<? super T> keyExtractor) { return thenComparing(Comparators.comparing(keyExtractor)); } }
--- a/src/share/classes/java/util/Comparators.java Fri Mar 08 16:02:27 2013 -0800 +++ b/src/share/classes/java/util/Comparators.java Fri Mar 08 21:54:17 2013 -0800 @@ -66,8 +66,7 @@ * * <p>The returned comparator is serializable. * - * @param <T> {@link Comparable} type - * + * @param <T> {@link Comparable} type * @return A comparator that imposes the reverse of the <i>natural * ordering</i> on a collection of objects that implement * the {@link Comparable} interface. @@ -78,27 +77,12 @@ } /** - * Returns a comparator that imposes the reverse ordering of the specified - * {@link Comparator}. - * - * <p>The returned comparator is serializable (assuming the specified - * comparator is also serializable). - * - * @param <T> the element type to be compared - * @param cmp a comparator whose ordering is to be reversed by the returned - * comparator - * @return A comparator that imposes the reverse ordering of the - * specified comparator. - */ - public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) { - Objects.requireNonNull(cmp); - return Collections.reverseOrder(cmp); - } - - /** * Gets a comparator compares {@link Comparable} type in natural order. * - * @param <T> {@link Comparable} type + * @param <T> {@link Comparable} type + * @return A comparator that imposes the <i>natural ordering</i> on a + * collection of objects that implement the {@link Comparable} + * interface. */ public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() { return (Comparator<T>) NaturalOrderComparator.INSTANCE; @@ -107,8 +91,9 @@ /** * Gets a comparator compares {@link Map.Entry} in natural order on key. * - * @param <K> {@link Comparable} key type - * @param <V> value type + * @param <K> {@link Comparable} key type + * @param <V> value type + * @return A comparator compares {@link Map.Entry} in natural order on key. */ public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> naturalOrderKeys() { return (Comparator<Map.Entry<K, V>> & Serializable) @@ -120,6 +105,7 @@ * * @param <K> key type * @param <V> {@link Comparable} value type + * @return A comparator compares {@link Map.Entry} in natural order on value. */ public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> naturalOrderValues() { return (Comparator<Map.Entry<K, V>> & Serializable) @@ -133,28 +119,49 @@ * <p>The returned comparator is serializable assuming the specified * comparators are also serializable. * - * @param <K> key type - * @param <V> value type - * @param cmp the key {@link Comparator} + * @param <K> key type + * @param <V> value type + * @param cmp the key {@link Comparator} + * @return A comparator compares {@link Map.Entry} by the key. */ public static <K, V> Comparator<Map.Entry<K, V>> byKey(Comparator<? super K> cmp) { - Objects.requireNonNull(cmp); - return (Comparator<Map.Entry<K, V>> & Serializable) - (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey()); + return comparing(Map.Entry<K, V>::getKey, cmp); } /** * Gets a comparator compares {@link Map.Entry} by value using the given * {@link Comparator}. * - * @param <K> key type - * @param <V> value type - * @param cmp the value {@link Comparator} + * @param <K> key type + * @param <V> value type + * @param cmp the value {@link Comparator} + * @return A comparator compares {@link Map.Entry} by the value. */ public static <K, V> Comparator<Map.Entry<K, V>> byValue(Comparator<? super V> cmp) { + return comparing(Map.Entry<K, V>::getValue, cmp); + } + + /** + * 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 + * specified {@link Comparator}. For example, if a class {@code Person} + * has a {@code String}-valued getter {@code getLastName}, then {@code + * comparing(Person::getLastName, String.CASE_INSENSITIVE_ORDER} would + * return a {@code Comparator<Person>} that compares {@code Person} + * objects by their last name ignoring case differences. + * + * @param <T> the original element type + * @param <U> the type for comparison + * @param keyExtractor the function used to extract the sort key + * @param cmp the {@code Comparator} used to compare the sort key + * @return A comparator compares by extracted key using specified {@code + * Comparator} + */ + public static <T, U> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> cmp) { + Objects.requireNonNull(keyExtractor); Objects.requireNonNull(cmp); - return (Comparator<Map.Entry<K, V>> & Serializable) - (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue()); + return (Comparator<T> & Serializable) + (c1, c2) -> cmp.compare(keyExtractor.apply(c1), keyExtractor.apply(c2)); } /** @@ -166,9 +173,10 @@ * Comparator<Person>} that compares {@code Person} objects by their last * name. * - * @param <T> the original element type - * @param <U> the {@link Comparable} type for comparison - * @param keyExtractor the function used to extract the {@link Comparable} sort key + * @param <T> the original element type + * @param <U> the {@link Comparable} type for comparison + * @param keyExtractor the function used to extract the {@link Comparable} sort key + * @return A comparator compares by extracted key */ public static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor) { Objects.requireNonNull(keyExtractor); @@ -177,15 +185,17 @@ } /** - * Accepts a function that extracts an {@code int} value from a type {@code - * T}, and returns a {@code Comparator<T>} that compares by that value. + * Accepts a function that extracts an {@code int} value from a type + * {@code T}, and returns a {@code Comparator<T>} that compares by that + * value. * - * <p>The returned comparator is serializable assuming the specified + * <p> The returned comparator is serializable assuming the specified * function is also serializable. * + * @param <T> the original element type + * @param keyExtractor the function used to extract the integer value + * @return A comparator compares by extracted key * @see #comparing(Function) - * @param <T> the original element type - * @param keyExtractor the function used to extract the integer value */ public static <T> Comparator<T> comparing(ToIntFunction<? super T> keyExtractor) { Objects.requireNonNull(keyExtractor); @@ -194,15 +204,17 @@ } /** - * Accepts a function that extracts a {@code long} value from a type {@code - * T}, and returns a {@code Comparator<T>} that compares by that value. + * Accepts a function that extracts a {@code long} value from a type + * {@code T}, and returns a {@code Comparator<T>} that compares by that + * value. * - * <p>The returned comparator is serializable assuming the specified + * <p> The returned comparator is serializable assuming the specified * function is also serializable. * + * @param <T> the original element type + * @param keyExtractor the function used to extract the long value + * @return A comparator compares by extracted key * @see #comparing(Function) - * @param <T> the original element type - * @param keyExtractor the function used to extract the long value */ public static <T> Comparator<T> comparing(ToLongFunction<? super T> keyExtractor) { Objects.requireNonNull(keyExtractor); @@ -215,12 +227,13 @@ * {@code T}, and returns a {@code Comparator<T>} that compares by that * value. * - * <p>The returned comparator is serializable assuming the specified + * <p> The returned comparator is serializable assuming the specified * function is also serializable. * + * @param <T> the original element type + * @param keyExtractor the function used to extract the double value + * @return A comparator compares by extracted key * @see #comparing(Function) - * @param <T> the original element type - * @param keyExtractor the function used to extract the double value */ public static<T> Comparator<T> comparing(ToDoubleFunction<? super T> keyExtractor) { Objects.requireNonNull(keyExtractor); @@ -229,36 +242,13 @@ } /** - * Constructs a lexicographic order from two {@link Comparator}s. For - * example, if you have comparators {@code byLastName} and {@code - * byFirstName}, each of type {@code Comparator<Person>}, then {@code - * compose(byLastName, byFirstName)} creates a {@code Comparator<Person>} - * which sorts by last name, and for equal last names sorts by first name. - * - * <p>The returned comparator is serializable assuming the specified - * comparators are also serializable. - * - * @param <T> the element type to be compared - * @param first the first comparator - * @param second the secondary comparator used when equals on the first - */ - public static<T> Comparator<T> compose(Comparator<? super T> first, Comparator<? super T> second) { - Objects.requireNonNull(first); - Objects.requireNonNull(second); - return (Comparator<T> & Serializable) (c1, c2) -> { - int res = first.compare(c1, c2); - return (res != 0) ? res : second.compare(c1, c2); - }; - } - - /** * Constructs a {@link BinaryOperator} which returns the lesser of two elements * according to the specified {@code Comparator} * - * @param comparator A {@code Comparator} for comparing the two values - * @param <T> the type of the elements to be compared + * @param comparator A {@code Comparator} for comparing the two values + * @param <T> the type of the elements to be compared * @return a {@code BinaryOperator} which returns the lesser of its operands, - * according to the supplied {@code Comparator} + * according to the supplied {@code Comparator} */ public static<T> BinaryOperator<T> lesserOf(Comparator<? super T> comparator) { return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; @@ -268,10 +258,10 @@ * Constructs a {@link BinaryOperator} which returns the greater of two elements * according to the specified {@code Comparator} * - * @param comparator A {@code Comparator} for comparing the two values - * @param <T> the type of the elements to be compared + * @param comparator A {@code Comparator} for comparing the two values + * @param <T> the type of the elements to be compared * @return a {@code BinaryOperator} which returns the greater of its operands, - * according to the supplied {@code Comparator} + * according to the supplied {@code Comparator} */ public static<T> BinaryOperator<T> greaterOf(Comparator<? super T> comparator) { return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;