Existe um equivalente em Java da COALESCE
função do SQL ? Ou seja, existe alguma maneira de retornar o primeiro valor não nulo de várias variáveis?
por exemplo
Double a = null;
Double b = 4.4;
Double c = null;
Eu quero de alguma forma tem uma declaração de que irá retornar o primeiro valor não nulo de a
, b
e c
- neste caso, ele voltaria b
, ou 4.4. (Algo como o método sql - return COALESCE(a,b,c)
). Eu sei que posso fazê-lo explicitamente com algo como:
return a != null ? a : (b != null ? b : c)
Mas me perguntei se havia alguma função incorporada e aceita para fazer isso.
Respostas:
Não, não existe.
O mais próximo que você pode chegar é:
Por razões eficientes, você pode lidar com os casos comuns da seguinte maneira:
fonte
coalesce(a, b)
, seb
é uma expressão complexa ea
não énull
,b
ainda é avaliado. Este não é o caso do operador condicional?:. Veja esta resposta .Apache Commons Lang 3
ObjectUtils.firstNonNull(T...)
Java 8 Stream
Stream.of(T...).filter(Objects::nonNull).findFirst().orElse(null)
fonte
Se houver apenas duas variáveis para verificar e você estiver usando o Guava, poderá usar MoreObjects.firstNonNull (T first, T second) .
fonte
Se houver apenas duas referências para testar e você estiver usando o Java 8, poderá usar
Se você importar estático opcional, a expressão não será muito ruim.
Infelizmente, seu caso com "várias variáveis" não é possível com um método opcional. Em vez disso, você pode usar:
fonte
Seguindo a resposta do LES2, você pode eliminar algumas repetições na versão eficiente, chamando a função sobrecarregada:
fonte
varargs
. Aqui, você está desperdiçando memória criando um quadro de pilha para cadacoalesce()
chamada aninhada . A chamadacoalesce(a, b, c, d, e)
cria até 3 quadros de pilha para calcular.Essa situação exige algum pré-processador. Como se você escrever uma função (método estático) que seleciona o primeiro valor não nulo, ela avalia todos os itens. É problemático se alguns itens forem chamadas de método (podem ser chamadas de método caras). E esses métodos são chamados mesmo se algum item antes deles não for nulo.
Algumas funcionam assim
deve ser usado, mas antes de compilar no código de bytes, deve haver um pré-processador que encontre usos dessa "função de coalescência" e a substitua por construções como
Atualização 2014-09-02:
Graças ao Java 8 e Lambdas, é possível ter uma verdadeira coalescência em Java! Incluindo o recurso crucial: expressões específicas são avaliadas apenas quando necessário - se uma anterior não for nula, as seguintes não serão avaliadas (métodos não são chamados, computação ou operações de disco / rede não são realizadas).
Eu escrevi um artigo sobre o Java 8: coalescer - hledáme neNULLové hodnoty - (escrito em tcheco, mas espero que os exemplos de código sejam compreensíveis para todos).
fonte
Com o Goiaba, você pode fazer:
que não lança NPE se ambos
a
eb
sãonull
.Edição: Eu estava errado, ele lança NPE. A maneira correta, como comentado por Michal Čizmazia, é:
fonte
java.lang.NullPointerException: use Optional.orNull() instead of Optional.or(null)
Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull()
Apenas para completar, o caso "várias variáveis" é realmente possível, embora nem um pouco elegante. Por exemplo, para as variáveis
o
,p
eq
:Por favor, note o uso de
orElseGet()
assistir ao caso queo
,p
eq
não são variáveis, mas expressões caro ou com efeitos colaterais indesejáveis.No caso mais geral
coalesce(e[1],e[2],e[3],...,e[N])
Isso pode gerar expressões excessivamente longas. No entanto, se estamos tentando mudar para um mundo sem
null
,v[i]
provavelmente já somos do tipoOptional<String>
, e não simplesmenteString
. Nesse caso,ou no caso de expressões:
Além disso, se você também está se movendo para um estilo funcional-declarativa,
o
,p
, eq
deve ser do tipoSupplier<String>
como em:E então o todo se
coalesce
reduz simplesmente ao.get()
.Para um exemplo mais concreto:
defaultAgeFromDatabase()
,ageFromDatabase()
EageFromInput()
já ia voltarOptional<Integer>
, naturalmente.E então o
coalesce
torna - seeffectiveAge.get()
ou simplesmenteeffectiveAge
se estamos felizes com aSupplier<Integer>
.IMHO, com o Java 8, veremos cada vez mais código estruturado dessa maneira, pois é extremamente auto-explicativo e eficiente ao mesmo tempo, especialmente em casos mais complexos.
Sinto falta de uma classe
Lazy<T>
que invocaSupplier<T>
apenas uma vez, mas preguiçosamente, além da consistência na definição deOptional<T>
(ieOptional<T>
-Optional<T>
operadores, ou mesmoSupplier<Optional<T>>
).fonte
Você pode tentar isso:
Com base nesta resposta
fonte
Que tal usar fornecedores quando você deseja evitar avaliar algum método caro?
Como isso:
E depois usá-lo assim:
Você também pode usar métodos sobrecarregados para as chamadas com dois, três ou quatro argumentos.
Além disso, você também pode usar fluxos com algo como isto:
fonte
Supplier
se ele será inspecionado de qualquer maneira? Por uma questão de uniformidade?E se:
O Java ArrayList permite convenientemente entradas nulas e essa expressão é consistente, independentemente do número de objetos a serem considerados. (Nesta forma, todos os objetos considerados precisam ser do mesmo tipo.)
fonte
fonte
Double
está longe de ser o ideal. Eu simplesmente não sabia que funções estáticas poderiam receber parâmetros de tipo. Eu pensei que eram apenas aulas.