Loose end: Comparators

Brian Goetz brian.goetz at oracle.com
Mon Jun 10 13:39:11 PDT 2013


Henry has been working on the set of Comparator factories, combinators, 
and defaults.  His explorations covered a lot of ground, and involved 
retreating in a few places where type inference didn't prove 
cooperative.  Here's where things are currently, and I'm pretty happy 
with this as an outcome -- I think its about the right set, though we 
can still niggle about naming and placement.

Comparators:

The (new) class Comparators goes away as a public class, now containing 
only package-private implementations.  The static methods from 
Comparators have been sent to other, arguably more appropriate places 
(as below -- some to Comparator, some to Map.Entry, some to BinaryOperator.)

Comparator -- static methods:

   // Natural order
   <T extends Comparable<? super T>> Comparator<T> naturalOrder()

   // Natural order, reversed
   <T extends Comparable<? super T>> Comparator<T> reverseOrder()

   // Comparator from key extraction function (5 forms)
   <T, U extends Comparable<? super U>> Comparator<T>
   comparing(Function<? super T, ? extends U> keyExtractor)

   <T, U> Comparator<T>
   comparing(Function<? super T, ? extends U> keyExtractor,
             Comparator<? super U> cmp)

   <T> Comparator<T> comparing(ToIntFunction<? super T> keyExtractor)
   <T> Comparator<T> comparing(ToLongFunction<? super T> keyExtractor)
   <T> Comparator<T> comparing(ToDoubleFunction<? super T> keyExtractor)

   // Null handling combinators
   <T> Comparator<T> nullsFirst(Comparator<? super T> comparator)
   <T> Comparator<T> nullsLast(Comparator<? super T> comparator)

Comparator -- default methods:

   // reverse the order of this comparator
   Comparator<T> reversed()

   // compose this comparator with another
   Comparator<T> thenComparing(Comparator<? super T> other)

   // compose this comparator with that implied by keyExtractor (x5)
   Comparator<T> thenComparing(ToIntFunction<? super T> keyExtractor)
   Comparator<T> thenComparing(ToLongFunction<? super T> keyExtractor)
   Comparator<T> thenComparing(ToDoubleFunction<? super T> keyExtractor)

   <U extends Comparable<? super U>> Comparator<T>
     thenComparing(Function<? super T, ? extends U> keyExtractor)

   <U> Comparator<T>
     thenComparing(Function<? super T, ? extends U> keyExtractor,
                   Comparator<? super U> cmp)

BinaryOperator -- static methods:

   // Was Comparators.lesserOf/greaterOf (useful as reducers)
   <T> BinaryOperator<T> minBy(Comparator<? super T> comparator)
   <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator)

Map.Entry -- static methods:

   // Was Comparators.naturalOrder{Keys,Values}
   <K extends Comparable<? super K>, V>
   Comparator<Map.Entry<K,V>> comparingByKey()

   <K, V extends Comparable<? super V>>
   Comparator<Map.Entry<K,V>> comparingByValue()

   // Was Comparators.by{Key,Value}
   <K, V> Comparator<Map.Entry<K, V>>
     comparingByKey(Comparator<? super K> cmp)

   <K, V> Comparator<Map.Entry<K, V>>
     comparingByValue(Comparator<? super V> cmp)

Notable changes from recent Lambda versions:

  - All attempts at adding "<S extends T>" flexibility have been rolled 
back.  This ran into conflicts with type inference that made it 
impractical to overload the ref/int/long/double methods without mangling 
the names (we're trying to restrict name mangling for cases where it 
actually adds value, which is mostly when it describes the result type 
of the operation, not the argument types.)

  - Accordingly, comparingFromXxx have been renamed back to comparing.

  - Static methods from Comparators have been sent to other, arguably 
more appropriate, places.



More information about the lambda-libs-spec-experts mailing list