Есть ли Java-эквивалент функции SQL COALESCE
? То есть есть ли способ вернуть первое ненулевое значение нескольких переменных?
например
Double a = null;
Double b = 4.4;
Double c = null;
Я хочу , чтобы как - то заявление , которое будет возвращать первое значение ненулевого из a
, b
и c
- в этом случае было бы вернуться b
, или 4,4. (Что-то вроде метода sql - возврат COALESCE(a,b,c)
). Я знаю, что могу сделать это явно с помощью чего-то вроде:
return a != null ? a : (b != null ? b : c)
Но мне было интересно, есть ли какая-нибудь встроенная, принятая функция для достижения этой цели.
Ответы:
Нет, нет
Самое близкое, что вы можете получить:
По эффективным причинам вы можете справиться с общими случаями следующим образом:
источник
coalesce(a, b)
, еслиb
это сложное выражение, аa
не нетnull
,b
все еще оценивается. Это не относится к условному оператору?: Смотрите этот ответ .Apache Commons Lang 3
ObjectUtils.firstNonNull(T...)
Java 8 Stream
Stream.of(T...).filter(Objects::nonNull).findFirst().orElse(null)
источник
Если нужно проверить только две переменные и вы используете Guava, вы можете использовать MoreObjects.firstNonNull (T first, T second) .
источник
Если есть только две ссылки для тестирования, и вы используете Java 8, вы можете использовать
Если вы импортируете static Optional, выражение не так уж плохо.
К сожалению, ваш случай с «несколькими переменными» невозможен при использовании Optional-метода. Вместо этого вы можете использовать:
источник
Следуя ответу LES2, вы можете устранить некоторые повторения в эффективной версии, вызвав перегруженную функцию:
источник
varargs
. Здесь вы тратите впустую память, создавая кадр стека для каждого вложенногоcoalesce()
вызова. Вызовcoalesce(a, b, c, d, e)
создает до 3 кадров стека для расчета.Эта ситуация требует некоторого препроцессора. Потому что, если вы напишите функцию (статический метод), которая выбирает первое ненулевое значение, она оценивает все элементы. Это проблема, если некоторые элементы являются вызовами методов (могут быть дорогостоящие вызовы методов). И эти методы вызываются, даже если любой элемент перед ними не равен нулю.
Некоторые функции, подобные этой
должен использоваться, но перед компиляцией в байт-код должен быть препроцессор, который находит использование этой «функции объединения» и заменяет ее конструкцией, подобной
Обновление 2014-09-02:
Благодаря Java 8 и Lambdas появилась возможность объединиться в Java! Включая критическую особенность: определенные выражения оцениваются только при необходимости - если ранее одно из них не является нулевым, то следующие не оцениваются (методы не вызываются, вычисления или операции с диском / сетью не выполняются).
Я написал статью об этом Java 8: coalesce - hledáme neNULLové hodnoty - (написано на чешском языке, но я надеюсь, что примеры кода понятны для всех).
источник
С Guava вы можете сделать:
который не бросает NPE, если оба
a
иb
естьnull
.РЕДАКТИРОВАТЬ: я был неправ, он бросает NPE. Правильный путь, который прокомментировал Михал Чизмия, таков :
источник
java.lang.NullPointerException: use Optional.orNull() instead of Optional.or(null)
Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull()
Просто для полноты, случай «нескольких переменных» действительно возможен, хотя и вовсе не элегантен. Например, для переменных
o
,p
иq
:Пожалуйста, обратите внимание на
orElseGet()
тоo
, что использование ,p
иq
не являются переменными, а выражениями, дорогими или с нежелательными побочными эффектами.В самом общем случае
coalesce(e[1],e[2],e[3],...,e[N])
Это может генерировать выражения чрезмерно долго. Однако, если мы пытаемся перейти в мир без
null
, тоv[i]
, скорее всего, это уже типOptional<String>
, а не простоString
. В таком случае,или в случае выражений:
Кроме того, если вы также переход к функционально-декларативному стилю
o
,p
иq
должно быть типа ,Supplier<String>
как в:И тогда все
coalesce
сводится просто кo.get()
.Для более конкретного примера:
defaultAgeFromDatabase()
,ageFromDatabase()
ИageFromInput()
было бы уже вернутьсяOptional<Integer>
, естественно.И тогда
coalesce
становитсяeffectiveAge.get()
или простоeffectiveAge
если мы довольны собойSupplier<Integer>
.ИМХО, с Java 8 мы увидим все больше и больше такого структурированного кода, поскольку он чрезвычайно понятен и эффективен одновременно, особенно в более сложных случаях.
Я действительно пропускаю класс,
Lazy<T>
который вызываетSupplier<T>
только один раз, но лениво, а также последовательность в определенииOptional<T>
(то естьOptional<T>
-Optional<T>
операторы или дажеSupplier<Optional<T>>
).источник
Вы можете попробовать это:
На основании этого ответа
источник
Как насчет использования поставщиков, если вы хотите избежать оценки какого-либо дорогостоящего метода?
Как это:
И затем использовать это так:
Вы также можете использовать перегруженные методы для вызовов с двумя, тремя или четырьмя аргументами.
Кроме того, вы также можете использовать потоки с чем-то вроде этого:
источник
Supplier
если он все равно будет проверен? Ради единообразия?Как насчет:
Java ArrayList удобно допускает нулевые записи, и это выражение является согласованным независимо от количества рассматриваемых объектов. (В этой форме все рассматриваемые объекты должны быть одного типа.)
источник
источник
Double
далеко не идеален. Я просто не знал, что статическим функциям могут быть заданы параметры типа. Я думал, что это были просто уроки.