Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8357219

Provide default methods min(T, T) and max(T, T) in Comparator interface

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Unresolved
    • Icon: P4 P4
    • None
    • core-libs
    • None
    • source
    • low
    • Hide
      As we are adding new default methods to an existing interface, there's a possibility of signature clash if override-equivalent methods were previously added in the implementations of these interfaces. The risk is considered to be low because:

      - Nowadays many users don't create new comparators directly, relying on combinator methods like `Comparator.comparing`.
      - Most of the implementations of `Comparator` interface are either functions (lambdas or method references) or declare only `compare` method.
      - If some implementations declare `min` and/or `max` method accepting two arguments, there are big chances that these methods are source-compatible with proposed ones. A concrete example is the `Ordering` interface from the Guava library, which provides source-compatible `min()` and `max()` methods with the same semantics:
      https://guava.dev/releases/snapshot-jre/api/docs/com/google/common/collect/Ordering.html#max(E,E)
      Show
      As we are adding new default methods to an existing interface, there's a possibility of signature clash if override-equivalent methods were previously added in the implementations of these interfaces. The risk is considered to be low because: - Nowadays many users don't create new comparators directly, relying on combinator methods like `Comparator.comparing`. - Most of the implementations of `Comparator` interface are either functions (lambdas or method references) or declare only `compare` method. - If some implementations declare `min` and/or `max` method accepting two arguments, there are big chances that these methods are source-compatible with proposed ones. A concrete example is the `Ordering` interface from the Guava library, which provides source-compatible `min()` and `max()` methods with the same semantics: https://guava.dev/releases/snapshot-jre/api/docs/com/google/common/collect/Ordering.html#max(E,E)
    • Java API

      Summary

      New default methods min() and max() are added to the Comparator interface, which allow finding greater or smaller of two objects, according to this Comparator.

      Problem

      While we have Stream.min/max and Collections.min/max, often it's required to select a greater or smaller object of two. Doing this with existing APIs is unnecessarily complicated. E.g., given two objects a and b and a comparator comp, we have the following possibilities to find the maximal object:

      • comp.compare(a, b) > 0 ? a : b

        This explicit version mentions both a and b twice and not very readable, as it requires matching the sign (> or <) with right-hand operands of ?: to understand whether we are looking for maximum or minimum

      • Stream.of(a, b).max(comp).get()

        Creates an unnecessary Optional which is always present and should be explicitly unwrapped. Also, depending on JIT compiler used and compilation tier, it may create unnecessary performance overhead and heap objects.

      • BinaryOperator.maxBy(comp).apply(a, b)

        While being the longest in terms of characters, it's probably the best of existing alternatives. However, it's not very discoverable and creates an unnecessary function when we just want to get the value.

      Solution

      It's suggested to extend the Comparator interface adding two default methods:

      public interface Comparator<T> {
      ...
          default T max(T a, T b) { ... }
      
          default T min(T a, T b) { ... }
      }

      The solution was preliminary discussed in core-libs-dev in this thread: https://mail.openjdk.org/pipermail/core-libs-dev/2025-May/145638.html

      Specification

          /**
           * Returns the greater of two values according to this comparator.
           * If the arguments are equal with respect to this comparator,
           * the {@code a} argument is returned.
           *
           * @param   a   an argument.
           * @param   b   another argument.
           * @return  the larger of {@code a} and {@code b} according to this comparator.
           * @throws  ClassCastException if the collection contains elements that are
           *          not <i>mutually comparable</i> (for example, strings and
           *          integers).
           *
           * @since 25
           */
          default T max(T a, T b) { ... }
      
          /**
           * Returns the smaller of two values according to this comparator.
           * If the arguments are equal with respect to this comparator,
           * the {@code a} argument is returned.
           *
           * @param   a   an argument.
           * @param   b   another argument.
           * @return  the smaller of {@code a} and {@code b} according to this comparator.
           * @throws  ClassCastException if the collection contains elements that are
           *          not <i>mutually comparable</i> (for example, strings and
           *          integers).
           *
           * @since 25
           */
          default T min(T a, T b) { ... }

            tvaleev Tagir Valeev
            tvaleev Tagir Valeev
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated: