¿Existe un equivalente Java de SQL COALESCE
función ? Es decir, ¿hay alguna forma de devolver el primer valor no nulo de varias variables?
p.ej
Double a = null;
Double b = 4.4;
Double c = null;
Quiero tener de alguna manera una declaración que devolverá el primer valor no nulo de a
, b
y c
- en este caso, sería volver b
, o 4.4. (Algo así como el método sql - return COALESCE(a,b,c)
). Sé que puedo hacerlo explícitamente con algo como:
return a != null ? a : (b != null ? b : c)
Pero me preguntaba si había alguna función incorporada y aceptada para lograr esto.
Respuestas:
No, no hay
Lo más cercano que puede llegar es:
Por razones eficientes, puede manejar los casos comunes de la siguiente manera:
fuente
coalesce(a, b)
, sib
es una expresión compleja ya
no lo esnull
,b
todavía se evalúa. Este no es el caso del operador condicional? Mira esta respuesta .Apache Commons Lang 3
ObjectUtils.firstNonNull(T...)
Java 8 Stream
Stream.of(T...).filter(Objects::nonNull).findFirst().orElse(null)
fuente
Si solo hay dos variables para verificar y está usando Guava, puede usar MoreObjects.firstNonNull (T primero, T segundo) .
fuente
Si solo hay dos referencias para probar y está utilizando Java 8, puede usar
Si importa estática Opcional, la expresión no es tan mala.
Lamentablemente, su caso con "varias variables" no es posible con un método opcional. En su lugar, podría usar:
fuente
Siguiendo con la respuesta de LES2, puede eliminar algunas repeticiones en la versión eficiente, llamando a la función sobrecargada:
fuente
varargs
. Aquí, está desperdiciando memoria creando un marco de pila para cadacoalesce()
llamada anidada . Llamarcoalesce(a, b, c, d, e)
crea hasta 3 cuadros de pila para calcular.Esta situación requiere algún preprocesador. Porque si escribe una función (método estático) que selecciona el primer valor no nulo, evalúa todos los elementos. Es un problema si algunos elementos son llamadas a métodos (pueden ser llamadas a métodos costosos). Y se llama a estos métodos incluso si algún elemento antes de ellos no es nulo.
Algunas funciones como esta
debe usarse, pero antes de compilar en el código de bytes, debe haber un preprocesador que encuentre el uso de esta "función de fusión" y la reemplace con una construcción como
Actualización 2014-09-02:
¡Gracias a Java 8 y Lambdas existe la posibilidad de tener una verdadera fusión en Java! Incluyendo la característica crucial: las expresiones particulares se evalúan solo cuando es necesario; si una anterior no es nula, las siguientes no se evalúan (no se llaman métodos, no se realizan operaciones de cálculo o de disco / red).
Escribí un artículo al respecto Java 8: fusión - hledáme neNULLové hodnoty - (escrito en checo, pero espero que los ejemplos de código sean comprensibles para todos).
fuente
Con guayaba puedes hacer:
que no arroja NPE si ambos
a
yb
sonnull
.EDITAR: Me equivoqué, arroja NPE. La forma correcta según lo comentado por Michal Čizmazia es:
fuente
java.lang.NullPointerException: use Optional.orNull() instead of Optional.or(null)
Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull()
Solo para completar, el caso de "varias variables" es realmente posible, aunque no es elegante en absoluto. Por ejemplo, para las variables
o
,p
yq
:Tenga en cuenta el uso de
orElseGet()
asistir al caso de queo
,p
yq
no son variables sino expresiones caros o con efectos secundarios no deseados.En el caso más general
coalesce(e[1],e[2],e[3],...,e[N])
Esto puede generar expresiones excesivamente largas. Sin embargo, si estamos tratando de mudarnos a un mundo sin él
null
, entoncesv[i]
lo más probable es que ya seamos de tipoOptional<String>
, en lugar de simplementeString
. En este caso,o en el caso de expresiones:
Por otra parte, si también se está moviendo a un estilo funcional declarativa,
o
,p
, yq
debe ser de tipoSupplier<String>
como en:Y luego todo se
coalesce
reduce simplemente ao.get()
.Para un ejemplo más concreto:
defaultAgeFromDatabase()
,ageFromDatabase()
YageFromInput()
sería ya volverOptional<Integer>
, naturalmente.Y luego se
coalesce
convierteeffectiveAge.get()
o simplementeeffectiveAge
si estamos contentos con unSupplier<Integer>
.En mi humilde opinión, con Java 8 veremos más y más código estructurado de esta manera, ya que es extremadamente autoexplicativo y eficiente al mismo tiempo, especialmente en casos más complejos.
Echo de menos una clase
Lazy<T>
que invocaSupplier<T>
solo una vez, pero perezosamente, así como la coherencia en la definición deOptional<T>
(es decirOptional<T>
,Optional<T>
operadores, o inclusoSupplier<Optional<T>>
).fuente
Puedes probar esto:
Basado en esta respuesta
fuente
¿Qué tal usar proveedores cuando quieres evitar evaluar algún método costoso?
Me gusta esto:
Y luego usarlo así:
También puede usar métodos sobrecargados para las llamadas con dos, tres o cuatro argumentos.
Además, también podría usar transmisiones con algo como esto:
fuente
Supplier
si será inspeccionado de todos modos? Por el bien de la uniformidad?Qué tal si:
Java ArrayList permite convenientemente entradas nulas y esta expresión es coherente independientemente del número de objetos a considerar. (De esta forma, todos los objetos considerados deben ser del mismo tipo).
fuente
fuente
Double
está lejos de ser ideal. Simplemente no sabía que las funciones estáticas podrían recibir parámetros de tipo. Pensé que solo eran clases.