Com certeza você já precisou percorrer uma lista, invocando métodos em cada um dos objetos nela contidos, certo? Então, neste post vou te mostrar como o Lambda do Java 8 veio para ajudar, para facilitar esse tipo de situação.
Vou começar apresentando a ideia do projeto, fazendo da maneira pré Java 8, e depois acrescentar o Lambda para você ver como é simples entendê-lo. Mas não é só isso, vou aproveitar e te mostrar mais algumas novidades do Java 8, como a classe java.time.LocalDate
, java.time.format.DateTimeFormatter
e métodos default
.
Temos um sistema financeiro que possui uma entidade Fatura
. Que representa a fatura de uma determinada compra, que não vamos relacionar aqui para facilitar o exemplo. Veja o código dela abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.algaworks.modelo; import java.time.LocalDate; public class Fatura { private String emailDevedor; private double valor; private LocalDate dataVencimento; public Fatura(String emailDevedor, double valor, LocalDate dataVencimento) { this .emailDevedor = emailDevedor; this .valor = valor; this .dataVencimento = dataVencimento; } // getters e setters } |
A ideia do sistema é, buscar as faturas vencidas e enviar um e-mail ao devedor lembrando-o sobre a dívida. Tarefa simples, não?
Para simplificar, não vou conectar no banco de dados, vamos apenas simular essa conexão já retornando uma lista com as faturas vencidas. Para isso, crie a classe FaturaDAO
como abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package com.algaworks.dao; import java.time.LocalDate; import java.util.Arrays; import java.util.List; import com.algaworks.modelo.Fatura; public class FaturaDAO { public List<Fatura> buscarFaturasVencidas() { // Você iria no banco de dados... Fatura f1 = new Fatura( "joao@joao.com" , 350.0 , LocalDate.now().minusDays( 3 )); Fatura f2 = new Fatura( "maria@maria.com" , 150.0 , LocalDate.now().minusMonths( 2 ).minusDays( 2 )); Fatura f3 = new Fatura( "jose@jose.com" , 200.0 , LocalDate.now().minusDays( 5 )); return Arrays.asList(f1, f2, f3); } } |
Deixa eu te explicar o que significa a linha:
1 | LocalDate.now().minusDays( 3 ) |
É tão simples quanto parece mesmo. Como eu não estou indo de fato no banco de dados, estou criando a classe Fatura com uma data passada, já vencida. Para isso eu utilizei o método now()
de LocalDate
para retornar a data de agora, logo em seguida o método minusDays(long diasASubtrair)
subtrai 3 dias da data atual. Fala verdade, se fosse com Calendar
daria um trabalho… :)
Agora que temos nosso modelo e a classe que os retorna do banco de dados, vamos criar uma classe que simulará o envio de e-mail. Mais uma vez vamos apenas simular o envio de e-mail, o objetivo aqui é mostrar o Lambda. Veja o código abaixo:
1 2 3 4 5 6 7 8 9 | package com.algaworks.email; public class EnviadorEmail { public void enviar(String to, String text) { // Aqui você utilizaria alguma biblioteca para enviar e-mail System.out.printf( "Enviando email para: %s. O Texto: %s\n" , to, text); } } |
Para passar o texto do e-mail, vamos criar um método resumo
na classe Fatura
que retorna o resumo da fatura, como a data de vencimento e o valor devido. Adicione o código abaixo:
1 2 3 4 | public String resumo() { String dataVencimento = this .dataVencimento.format(DateTimeFormatter.ofPattern( "dd/MM/yyyy" )); return String.format( "Valor R$ %s, vencimento: %s" , this .valor, dataVencimento); } |
Repare como ficou fácil formatar uma data. O DateTimeFormatter
possui várias opções de formatação, mas você pode criar sua própria, usando o método ofPattern
como fizemos acima.
Neste momento já temos tudo que precisamos para criar nossa classe de exemplo e eu finalmente te mostrar o Lambda em ação.
Crie a classe com.algaworks.exemplo.Exemplo
com o método main
e vamos começar a implementar a lógica de percorrer a lista e enviar os e-mails.
Veja abaixo como ficaria a implementação na forma tradicional:
1 2 3 4 5 6 7 | public static void main(String[] args) { EnviadorEmail enviadorEmail = new EnviadorEmail(); List<Fatura> faturasVencidas = new FaturaDAO().buscarFaturasVencidas(); for (Fatura f : faturasVencidas) { enviadorEmail.enviar(f.getEmailDevedor(), f.resumo()); } |
Tudo normal, certo? Então vamos começar a introduzir o Lambda de fato. Nós podemos substituir totalmente a linha que contém a instrução for
. Pois foi adicionado um método em java.lang.Iterable
chamado forEach
. Veja a documentação java.lang.Iterable.
Se você viu a documentação, viu que é um novo método em uma interface o que poderia ser um grande problema, pois todas as classes deveriam ter que implementá-lo. Você estaria certo, se não fosse um detalhe, a palavra chave default
adicionado na frente desse método. Agora a interface pode ter uma implementação, isso mesmo, interfaces podem ter implementação desde que o método seja marcado como default
. Mais detalhes sobre isso vou deixar para um outro post.
Vamos seguir e substituir o for
e utilizar o forEach
. Traduza o forEach
– para cada. Então pense assim, para cada elemento dentro da minha lista, faça alguma coisa. Veja o código abaixo:
1 | faturasVencidas.forEach((Fatura f) -> {}); |
O que estou fazendo ali é a mesma coisa do for
. O “f”, em Fatura f
, recebe cada elemento da lista. Entre as chaves é onde vou colocar o código que quero executar, no nosso caso utilizar o objeto para enviar o e-mail. Ficando assim:
1 2 3 | faturasVencidas.forEach((Fatura f) -> { enviadorEmail.enviar(f.getEmailDevedor(), f.resumo()); }); |
Mas o compilador já sabe que sua lista é de Fatura
. Então você pode omitir o tipo, deixando simplesmente assim:
1 2 3 | faturasVencidas.forEach(f -> { enviadorEmail.enviar(f.getEmailDevedor(), f.resumo()); }); |
E para melhorar ainda mais, como só temos uma linha de código para executar, podemos retirar as chaves e o ponto-e-vírgula de dentro do bloco. Veja:
1 | faturasVencidas.forEach(f -> enviadorEmail.enviar(f.getEmailDevedor(), f.resumo())); |
Muito simples! Te falei que seria simples de entender. :)
Se você tivesse que executar algum outro código e não somente uma linha, por exemplo, configurar uma variável dizendo que o e-mail foi enviado para você não enviar novamente. Poderia deixar o código como abaixo:
1 2 3 4 | faturasVencidas.forEach(f -> { enviadorEmail.enviar(f.getEmailDevedor(), f.resumo()); f.setNotificacaoEnviada( true ); }); |
É isso que gostaria de deixar para você.
Deixe seu comentário do que você achou da funcionalidade, se você achou realmente mais fácil.
Acesse ou baixe o código-fonte completo deste artigo no GitHub.
Para aprender mais sobre Java 8, conheça nosso curso online de Java e Orientação a Objetos, que é completo e substitui a necessidade de cursos presenciais.
Olá,
o que você achou deste conteúdo? Conte nos comentários.