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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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.