Java e OO

Introdução ao Lambda do Java 8

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

Graduado em Engenharia Elétrica pela Universidade Federal de Uberlândia e detentor das certificações LPIC-1, SCJP e SCWCD.

Olá,

o que você achou deste conteúdo? Conte nos comentários.

Junte-se a mais de 100.000 pessoas

Entre para nossa lista e receba conteúdos exclusivos e com prioridade

Você se Inscreveu com Sucesso!