Aproveite o mês das
carreiras na Alura

Até 44% OFF

Falta pouco!

00

DIAS

00

HORAS

00

MIN

00

SEG

Java 8: Lambda ou method reference? Entenda a diferença

Alura
lucas.romao
lucas.romao

Compartilhe

Introdução

O Java 8 trouxe algumas novas funcionalidades e dentre elas a possibilidade de usarmos lambdas e method references. Caso ainda não esteja familiarizado com esses recursos, talvez se interesse pelo nosso post de o mínimo que você deve saber sobre Java 8. As duas features são relacionadas e nos ajudam a reduzir a quantidade de código escrito, com uma abordagem um pouco mais funcional.

Para dar um exemplo de uso de cada uma delas, vamos supor que temos uma lista de nomes e que gostaríamos de imprimir seu conteúdo. Antes do lambda e method reference, o código ficaria dessa forma:

 List<String> nomes = Arrays.asList(“Lucas”, “Rodrigo”, “Paulo”); for(String nome : nomes) { System.out.println(nome); } 

Que nos resultaria na saída:

 Lucas Rodrigo Paulo 

Esse mesmo código, com uso da expressão lambda e o método default forEach, poderia ficar assim, em uma única linha:

 nomes.forEach(nome -> System.out.println(nome)); 

E daria para fazer o mesmo com o method reference, deixando ainda mais simples:

 nomes.forEach(System.out::println); 

Em todos os casos teríamos a mesma saída:

 Lucas Rodrigo Paulo 

Mas qual a real diferença entre essas abordagens? Qual das duas versões você prefere usar no seu dia a dia?

Banner da Imersão de IA da Alura com Google Gemini. Participe de aulas gratuitas online com certificado. Domine as inovações mais recentes da IA.

Existe uma opção melhor para todos os casos?

Ao perceber que as features fazem coisas parecidas é normal se perguntar qual delas é a melhor. A resposta seria depende, nenhuma delas é a melhor solução para todos os casos. Entender a diferença entre elas é fundamental para saber quando é o melhor momento de usar cada uma.

Podemos usar method reference sempre?

É importante ressaltar que nem sempre é possível substituir um lambda por um method reference. Para conseguir fazer uma chamada a um method reference é necessário que a invocação de método da direita receba os mesmos parâmetros da esquerda do lambda.

No exemplo abaixo temos a nossa lista de nomes e queremos criar uma nova lista apenas com apenas as primeiras 3 letras de cada nome.

 List<String> nomes = Arrays.asList(“Lucas”, “Rodrigo”, “Alura”);
List<String> nomesReduzidos = nomes .map(nome -> nome.substring(0, 3)) .collect(Collectors.toList()); 

Nesse caso não seria possível usar o method reference, uma vez que para chamar o método substring seria necessário passar um parâmetro externo, os números 0 e 3, que definem o início e fim da nova string.

Vantagens de se usar Method Reference

Apesar de não poder ser usado em todos os casos onde se usa a lambda, method references possuem algumas vantagens bem legais. A primeira delas está no fato de usar menos símbolos, o que facilita bastante a legibilidade do código.

Há uma outra vantagem, que é a facilidade de se entender o que está sendo manipulado, uma vez que o tipo do objeto fica sempre muito explícito. Para exemplificarmos: suponha que temos uma classe Pessoa e essa classe possui o método getName, utilizando lambda para chamar esse método faríamos algo do tipo:

 p -> p.getName() 

Veja que é necessário entender qual o contexto para poder entender o que é o *p*, enquanto com method reference, teríamos algo como

 Pessoa::getName 

Fica bem mais fácil identificar o elemento que está sendo manipulado, percebe? Está explicito.

Outros usos do method reference

Um uso para o method reference que nem sempre é de conhecimento geral é que ele também funciona em métodos que recebem mais de um parâmetro, contanto que a quantidade seja a mesma que a de atributo do objeto que estamos usando.

Imagine que temos um mapa de alunos e sua nota, e gostaríamos de passar isso para um outro mapa.

Usando lambdas, nosso código seria:

 Map<String, Integer> novoMapaDeNotas = new HashMap<String, Integer>(); notasAlunos.forEach( (nome, nota) -> novoMapaDeNotas.put(nome, nota)); 

Veja que o lado esquerdo do lambda recebe dois parâmetros, o nome e a nota. O lado direito também recebe esses parâmetros, nessa mesma ordem. Que tal então fazer dessa forma, com method reference:

 Map<String, Integer> novoMapaDeNotas = new HashMap<String, Integer>(); notasAlunos.forEach(novoMapaDeNotas::put); 

E quanto a diferença de performance?

Pensando na questão de performance o lambda faz uma chamada de método a mais do que o method reference para executar o método, e as duas abordagens resultam em bytecodes diferentes, entretanto para a maioria dos casos essa diferença não chega a afetar performance. Só precisa ser levada em consideração em sistemas críticos onde a performance é essencial, não no forEach e manipulações simples do dia a dia.

E você, já tem usado Java 8 e esses recursos em seus projetos de produção? Aqui na Caelum e Alura usamos bastante. Tem até um curso dando uma visão bem legal sobre as novidades dessa versão.

Veja outros artigos sobre Programação