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!

Blog da AlgaWorks
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.