<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4" face="monospace">When we did Lambda, we made a few
      mistakes in the category of adding default methods to some "highly
      abstract" types, such as Function::andThen.  You were there; these
      were well-intentioned, but we neglected to think sufficiently
      about the consequences for subclasses.  For example:<br>
      <br>
          interface Function<T,U> { <br>
              U apply(T t);<br>
      <br>
              <V> default Function<T, V>
      andThen(Function<U,V> g) { ... }<br>
          }<br>
      <br>
      seems fine, but then when you extend it:<br>
      <br>
          interface UnaryOperator<T> extends Function<T,T> {
      <br>
          }<br>
      <br>
      you kind of lose, because you can't compose _unary operators_
      using Function::compose.  And if you try to refine it:<br>
      <br>
    </font><font size="4" face="monospace">    interface
      UnaryOperator<T> extends Function<T,T> { <br>
    </font><font size="4" face="monospace">        default
      UnaryOperator<T> andThen(UnaryOperator<T> g) { ... }<br>
    </font><font size="4" face="monospace">    }<br>
      <br>
      you end up overloading, not overriding the method, in a way that
      clients cannot distinguish: `f.andThen(lambda)` will likely not be
      able to distinguish between the overloads, because they have the
      same shape.  Ooops.  <br>
      <br>
      So with that as background, I am very cautious to consider adding
      methods to Comparable, because it is a highly abstract type that
      was designed for extension, and the risk of the above kind of
      clash seems "not low".  <br>
      <br>
      Comparator seems less risky, because it is not designed to be
      extended by domain objects, but instead functions more like a type
      class in Haskell -- it is behavior _about_ a type, defined from
      the outside.  And Haskell would agree with you that this move is
      sensible; here's Haskell's `Ord` (like Comparator), which extends
      `Eq` (providing equality.)<br>
      <br>
      class  (Eq a) => Ord a  where<br>
          compare              :: a -> a -> Ordering<br>
          (<), (<=), (>), (>=) :: a -> a -> Bool<br>
          max, min             :: a -> a -> a<br>
      <br>
          compare x y = if x == y then EQ<br>
                        -- NB: must be '<=' not '<' to validate
      the<br>
                        -- above claim about the minimal things that<br>
                        -- can be defined for an instance of Ord:<br>
                        else if x <= y then LT<br>
                        else GT<br>
      <br>
          x <= y = case compare x y of { GT -> False; _ -> True
      }<br>
          x >= y = y <= x<br>
          x > y = not (x <= y)<br>
          x < y = not (y <= x)<br>
      <br>
      <br>
              -- These two default methods use '<=' rather than
      'compare'<br>
              -- because the latter is often more expensive<br>
          max x y = if x <= y then y else x<br>
          min x y = if x <= y then x else y<br>
          {-# MINIMAL compare | (<=) #-}<br>
      <br>
      The `compare` method is like our Comparator method, just returning
      a three-valued enum rather than an int.  (Haskell has a cool
      feature here, where you can define all the methods in terms of
      others, and then you can override whichever ones make sense to
      break the cycles.  The MINIMAL annotation says "if you provide
      either compare or <=, you're good."  I wish we had this for
      interfaces with default methods.)  It then proceeds to derive
      `min` and `max` from `<=` (which might itself be derived from
      `compare`.)  <br>
      <br>
      OK, "comparative languages" lesson over, back to your point. 
      There are two ways to get where you want: a static method that
      takes a comparator and the operands (`Comparator.max(c, a, b)`),
      or a default method on Comparator (`c.max(a, b)`).  (You say "add
      simple static methods ... to Comparator" but I think you mean to
      put the word `static` elsewhere in that sentence.)<br>
      <br>
      I am receptive to the idea of extending Comparator here, but would
      want to think about it more to feel out potential mistakes like
      the `andThen` one above.  But your point is solid: a "comparator"
      is also a "maxxer" and a "minner" (neither of those are words, and
      if they were, are probably spelled wrong), and that is a natural
      place to locate such behavior.  <br>
      <br>
      <br>
    </font><br>
    <br>
    <div class="moz-cite-prefix">On 5/13/2025 10:12 AM, Tagir Valeev
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAE+3fja-oo=Yxxs9gQ9cTnCStYOBtf1oey3Dn6F2dNjbfievCg@mail.gmail.com">
      
      <div dir="ltr">Hello!
        <div><br>
        </div>
        <div>Several times already when writing Java programs, I
          stumbled with a simple task: given two objects with natural
          order, find the maximal of them. The algorithm I need could be
          formulated like this:</div>
        <div><br>
        </div>
            <T extends Comparable<T>> T max(T a, T b) {<br>
                return a.compareTo(b) > 0 ? a : b; <br>
            }<br>
        <div><br>
        </div>
        <div>Writing manually compareTo >= 0 looks too verbose, not
          very readable and error-prone: one has to mention both objects
          twice, and it's possible to mix > with <. I can surely
          add a method mentioned above to a utility class in my project
          and use it everywhere. However, I feel that it deserves a
          place in the standard library.</div>
        <div><br>
        </div>
        <div>The alternatives we have now:</div>
        <div>BinaryOperator.maxBy(Comparator.<T>naturalOrder()).apply(a,
          b);</div>
        <div>This speaks clearly about the intent (we'd like to get the
          maximum and we write 'maxBy') but very wordy.</div>
        <div><br>
        </div>
        <div>Stream.of(a, b).max(Comparator.naturalOrder()).get();</div>
        <div>Also clear and a little bit shorter, but has an unnecessary
          Optional in-between (we know that we have at least one
          element, so the result is always present) and we have to
          mention the comparator. Finally, it might be much less
          efficient than expected.</div>
        <div><br>
        </div>
        <div>Probably we can add simple static methods `max` and `min`
          either to the `Comparator` interface, or to
          `java.util.Objects`? Such methods would complement methods
          from the `Math` class for numbers. In addition, having default
          methods `max` and `min` in the `Comparator` interface would
          also be nice:<br>
          <br>
          String bigger = String.CASE_INSENSITIVE_ORDER.max("Hello",
          "world");<br>
          <br>
          What do you think? Can we proceed with such an enhancement?</div>
        <div><br>
        </div>
        <div>With best regards,</div>
        <div>Tagir Valeev</div>
      </div>
    </blockquote>
    <br>
  </body>
</html>