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. Also, this version would require an explicit type argument if the comparator is defined for a more abstract type:
```
Comparator<CharSequence> comp = Comparator.comparingInt(CharSequence::length);
// Here <String> is necessary
String max = BinaryOperator.<String>maxBy(comp).apply("long", "short");
```
Solution
--------
It's suggested to extend the `Comparator` interface adding two default methods:
```
public interface Comparator<T> {
...
default <U extends T> U max(U o1, U o2) { ... }
default <U extends T> U min(U o1, U o2) { ... }
}
```
The solution was preliminarily 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 o1} argument is returned.
*
* @param o1 an argument.
* @param o2 another argument.
* @param <U> the type of the arguments and the result.
* @return the larger of {@code o1} and {@code o2} according to this comparator.
* @throws NullPointerException if an argument is null and this
* comparator does not permit null arguments
* @throws ClassCastException if the arguments' types prevent them from
* being compared by this comparator.
*
* @since 25
*/
default <U extends T> U max(U o1, U o2) { ... }
/**
* Returns the smaller of two values according to this comparator.
* If the arguments are equal with respect to this comparator,
* the {@code o1} argument is returned.
*
* @param o1 an argument.
* @param o2 another argument.
* @param <U> the type of the arguments and the result.
* @return the smaller of {@code o1} and {@code o2} according to this comparator.
* @throws NullPointerException if an argument is null and this
* comparator does not permit null arguments
* @throws ClassCastException if the arguments' types prevent them from
* being compared by this comparator.
*
* @since 25
*/
default <U extends T> U min(U o1, U o2) { ... }
```