No Java 8, quero fazer algo com um Optional
objeto, se estiver presente, e fazer outra coisa, se não estiver presente.
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
Este não é um 'estilo funcional', no entanto.
Optional
tem um ifPresent()
método, mas não consigo encadear um orElse()
método.
Assim, não posso escrever:
opt.ifPresent( x -> System.out.println("found " + x))
.orElse( System.out.println("NOT FOUND"));
Em resposta a @assylias, acho que não Optional.map()
funciona para o seguinte caso:
opt.map( o -> {
System.out.println("while opt is present...");
o.setProperty(xxx);
dao.update(o);
return null;
}).orElseGet( () -> {
System.out.println("create new obj");
dao.save(new obj);
return null;
});
Nesse caso, quando opt
presente, atualizo sua propriedade e salvo no banco de dados. Quando não está disponível, eu crio um novo obj
e salvo no banco de dados.
Nota nas duas lambdas eu tenho que voltar null
.
Mas quando opt
estiver presente, as duas lambdas serão executadas. obj
será atualizado e um novo objeto será salvo no banco de dados. Isso ocorre por causa do return null
primeiro lambda. E orElseGet()
continuará a executar.
fonte
return null;
porreturn o;
(ambos). No entanto, tenho a forte sensação de que você está trabalhando no lugar errado. Você deve trabalhar no site que produziu issoOptional
. Nesse local, deve haver uma maneira de realizar a operação desejada sem o intermediárioOptional
.ifPresent
isso contradiz. Todos os outros métodos se referem ao valor e não às ações.Respostas:
Para mim, a resposta de @Dane White é boa, primeiro não gostei de usar o Runnable, mas não encontrei alternativas, aqui outra implementação preferi mais
Então :
Atualização 1:
a solução acima para a maneira tradicional de desenvolvimento quando você tem o valor e deseja processá-lo, mas e se eu quiser definir a funcionalidade e a execução será então, verifique abaixo o aprimoramento;
Então poderia ser usado como:
Neste novo código, você tem três coisas:
a propósito, agora seu nome é mais descritivo, na verdade é Consumidor>
fonte
Se você estiver usando Java 9+, poderá usar o
ifPresentOrElse()
método:fonte
O Java 9 apresenta
ifPresentOrElse se um valor estiver presente, executa a ação especificada com o valor, caso contrário, executa a ação baseada em vazio especificada.
Veja excelente Opcional na cábula Java 8 .
Ele fornece todas as respostas para a maioria dos casos de uso.
Breve resumo abaixo
ifPresent () - faça algo quando Opcional estiver definido
filter () - rejeita (filtra) determinados valores opcionais.
map () - transforma valor se presente
orElse () / orElseGet () - ficando vazio Opcional para o padrão T
orElseThrow () - lança preguiçosamente exceções em vazio
fonte
map
, mas é um pouco estranho pedir uma solução funcional para que você possa chamar um DAO. Parece-me que faria mais sentido retornar o objeto atualizado / novo dessemap.orElse
bloco e fazer o que você precisa fazer com o objeto retornado.map
foco no próprio fluxo e não se destina a "fazer coisas com outro objeto, dependendo do status desse elemento no fluxo". É bom saber queifPresentOrElse
é adicionado em Java 9.Uma alternativa é:
Eu não acho que melhora a legibilidade, no entanto.
Ou, como Marko sugeriu, use um operador ternário:
fonte
new Object();
no seu primeiro lambda, mas para ser honesto, isso se torna muito feio. Gostaria de manter um if / else para o seu exemplo atualizado.map
apenas retornarOptional
para encadear torna o código mais difícil de entender, enquantomap
se supõe que ele seja literalmente mapeado para alguma coisa.Outra solução seria usar funções de ordem superior da seguinte maneira
fonte
value -> () -> syso
parte significa.String result = opt.map(value -> "withOptional").orElse("without optional");
Não há uma ótima maneira de fazer isso imediatamente. Se você quiser usar a sintaxe do limpador regularmente, poderá criar uma classe de utilitário para ajudar:
Em seguida, você pode usar uma importação estática em outro lugar para obter a sintaxe mais próxima do que deseja:
fonte
Optional.ifPresentOrElse()
foi adicionado ao JDK 9.Se você pode usar apenas o Java 8 ou inferior:
1) se você não tem
spring-data
a melhor maneira até agora é:Agora eu sei que não é tão legível e até difícil de entender para alguém, mas parece bom para mim pessoalmente e não vejo outra maneira fluente e agradável para este caso.
2) se você tiver sorte e puder usar
spring-data
da melhor maneira, é Opcional # ifPresentOrElse :Se você pode usar o Java 9, definitivamente deve usar:
fonte
O comportamento descrito pode ser alcançado usando o Vavr (anteriormente conhecido como Javaslang), uma biblioteca funcional de objetos para Java 8+, que implementa a maioria das construções do Scala (sendo o Scala uma linguagem mais expressiva com um sistema do tipo mais rico construído na JVM). É uma biblioteca muito boa para adicionar aos seus projetos Java para escrever código funcional puro.
O Vavr fornece a
Option
mônada que fornece funções para trabalhar com o tipo de opção, como:fold
: para mapear o valor da opção nos dois casos (definido / vazio)onEmpty
: permite executar umaRunnable
opção quando estiver vaziapeek
: permite consumir o valor da opção (quando definido).Serializable
pelo contrário, oOptional
que significa que você pode usá-lo com segurança como argumento do método e membro da instância.A opção segue as leis da mônada diferentes da "pseudo-mônada" opcional do Java e fornece uma API mais rica. E é claro que você pode fazer isso a partir de um Java opcional (e vice-versa):
Option.ofOptional(javaOptional)
vice versa –Vavr está focado na interoperabilidade.Indo para o exemplo:
Leitura adicional
Referência nula, o erro de um bilhão de dólares
Nota: este é apenas um pequeno exemplo do que o Vavr oferece (correspondência de padrões, fluxos também conhecidos como listas de avaliação lenta, tipos monádicos, coleções imutáveis, ...).
fonte
Outra solução pode ser a seguinte:
É assim que você o usa:
Ou no caso de você, no caso de uso oposto, ser verdadeiro:
Estes são os ingredientes:
A interface de função aprimorada "cosmeticamente".
E a classe Wrapper opcional para aprimoramento:
Isso deve funcionar e pode servir como um modelo básico de como lidar com esses requisitos.
A idéia básica aqui é a seguir. Em um mundo de programação de estilo não funcional, você provavelmente implementaria um método com dois parâmetros, onde o primeiro é um tipo de código executável que deve ser executado caso o valor esteja disponível e o outro parâmetro é o código executável que deve ser executado caso o O valor não está disponível. Para melhor legibilidade, você pode usar o curring para dividir a função de dois parâmetros em duas funções de um parâmetro cada. Foi o que basicamente fiz aqui.
Dica: Opt também fornece o outro caso de uso em que você deseja executar um trecho de código, caso o valor não esteja disponível. Isso também pode ser feito via Optional.filter.stuff, mas achei muito mais legível.
Espero que ajude!
Boa programação :-)
fonte
Caso você queira armazenar o valor:
fonte
Supondo que você tenha uma lista e evitando o
isPresent()
problema (relacionado aos opcionais), você pode usar.iterator().hasNext()
para verificar se não está presente.fonte