Мин / Макс функция с двумя сопоставимыми
У меня есть следующий фрагмент:
Comparable<C> a = ...;
Comparable<C> b = ...;
Comparable<C> min = a.compareTo(b) <= 0 ? a : b;
Это похоже на Math.min(a, b)
, но определено на Comparable
,
Я знаю, что троичный оператор уже довольно короткий, но я не могу встроить выражения для a
а также b
и я думаю, что min(a, b)
соответственно max(a, b)
легче понять.
Я знаю, что есть несколько потоков, соответственно. функции коллекции для набора значений, таких как:
Stream.of(a, b).min(Comparator.naturalOrder())
Это помогло бы встроить выражения, но мне все еще трудно читать и слишком много накладных расходов для такой маленькой задачи.
На данный момент я использую свою собственную служебную функцию, но мне интересно:
Как найти минимум два сопоставимых в удобочитаемом и библиотечно-независимом виде без слишком большого снижения производительности?
5 ответов
От
java.util.Collections
:Collections.max()
а такжеCollections.min()
Comparable<C> a = ...; Comparable<C> b = ...; Comparable<C> min = Collections.min(Arrays.asList(a,b));
От
org.apache.commons.lang.ObjectUtils
:ObjectUtils.max()
а такжеObjectUtils.min()
Comparable<C> a = ...; Comparable<C> b = ...; Comparable<C> min = ObjectUtils.min(a, b);
Я создал свой собственный вспомогательный класс, который расширяет Comparable
от min
, max
, isLessThan
, isLessOrEqualTo
, isGreaterThan
а также isGreaterOrEqualTo
:
public interface Ordered<T> extends Comparable<T> {
static <T extends Comparable<T>> T min(T a, T b) {
return a.compareTo(b) <= 0 ? a : b;
}
static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
default boolean isLessThan(T other) {
return compareTo(other) < 0;
}
default boolean isLessOrEqualTo(T other) {
return compareTo(other) <= 0;
}
default boolean isGreaterThan(T other) {
return compareTo(other) > 0;
}
default boolean isGreaterOrEqualTo(T other) {
return compareTo(other) >= 0;
}
}
min
а также max
методы, которые я использую для любого сопоставимого:
String first = "a";
String second = "b";
System.out.println(Ordered.min(first, second)); // Prints "a"
Для моих собственных реализаций Comparable
Я расширяю Ordered
и используйте это для удобочитаемых сравнений. Очень полезно для перечислений:
public enum Board implements Ordered<Board> {
NONE,
BREAKFAST,
HALF_BOARD,
FULL_BOARD,
ALL_INCLUSIVE
}
Использование:
Board requestedBoard = ...;
Board availableBoard = ...;
if (requestedBoard.isLessOrEqualTo(availableBoard)) {
...
}
Сторонние решения
Collections
имеет max(collection)
а также min(collection)
методы, которые делают то, что вы хотите.
Приносить целую новую библиотеку только для того, чтобы встроить одну простую операцию, может быть излишним, если у вас в смеси нет Apache Commons или Guava.
ручная работа с потенциально опасным литьем без литья
public <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
public <T extends Comparable<T>> T min(T a, T b) {
return a.compareTo(b) < 0 ? a : b;
}
Библиотека Google Guava имеетComparators.min
и Comparators.max
методы с версии 30.0:
Comparable<C> min = Comparators.min(a, b);
С использованием
Stream
Comparable<C> min = Stream.of(a, b).min(Comparable::compareTo).get();
Обратите внимание, что обычно вы не звоните
get()
и назначить, но использовать
ifPresent(min -> ...)
вместо. Но в этом случае вы можете доверять присутствию значения, поскольку поток не пуст.