Lambda, Lambda, Lambda Java
Sim o Lambda existe no Java 8 e vamos entender como ele funciona para finalmente aplicarmos no código... Lambda, Lambda, Lambda pra você \o/
Em meados de 2015 foi lançado o Java 8 com várias novas funcionalidades e mudanças em sua estrutura, não se trata apenas de uma atualização somente na plataforma, mas finalmente na linguagem, que na minha opinião o Java 8 foi uma atualização tão importante e com o mesmo impacto da versão 5, que foi um grande marco na linguagem. Porém, muitos ainda não estão utilizando os novos recursos, seja por não terem oportunidades ou ainda não as conhecem.
Neste primeiro artigo iremos tentar elucidar você sobre um desses recursos: Lambda Expression.
As expressões lambda ou apenas Lambda, são funcionalidades comuns em muitas linguagens, particularmente falando, nas linguagens Funcionais (Programação Funcional, LISP, Ruby, JavaScript etc) e o termo Lambda vem do Cálculo Lambda, ou seja, da matemática.
"Em ciência da computação, programação funcional é um paradigma de programação que trata a computação como uma avaliação de funções matemáticas e que evita estados ou dados mutáveis. Ela enfatiza a aplicação de funções, em contraste da programação imperativa, que enfatiza mudanças no estado do programa[1]."
Para entender bem sobre Lambda ou pelo menos ter familiaridade você irá precisar conhecer os conceitos de funções de primeira classe e literais.
No Java, um método por exemplo, existe como membro de uma classe que mesmo que você possa ter uma variável "apontando" para um objeto, você não vai poder guardar um método em uma variável.
Resumindo, tudo aquilo que é permitido referenciar numa linguagem (objetos ou tipos primitivos), passar parâmetros para outras funções é dito ser de "primeira classe".
Por exemplo, outras linguagens como o JavaScript permitem que funções e outras coisas sejam referenciados e passados como argumento:
function teste() { alert("teste"); }
var x = teste;
x(); // Alerta "teste"
Ou de uma outra forma:
var teste = function() { alert('teste'); };
Quando uma linguagem tem suporte a funções de primeira classe isso simplifica e muito a construção de certas funções. Vejamos um exemplo disso...
Imagine que você possui uma lista e gostaria de especificar um critério bem específico de comparação, então passamos uma função como parâmetro para o método ordenar:
funcaoOrdenar([...], function(a,b) { /*codigo que compara X e Y */ })
Isso em JavaScript, já no Java 1 a 7 teremos que criar uma classe específica para conter essa função:
class MeuComparador implements Comparator {
int compare(Object x, Object y) { /* compara X e Y */ }
}
funcaoOrdenar([...], new MeuComparador());
Você já deve estar familiarizado na linguagem Java. Porém com Lambda isso vai bem mais além, não só é permitido você passar funções como também parâmetros para outras funções, mas permitindo também que as mesmas sejam expressas como literais.
"Um literal é uma notação que representa um valor fixo no seu código, ou seja, através do uso da própria sintaxe você cria um objeto que de outra forma iria exigir a combinação de duas ou mais funcionalidades diferentes(Classes, variáveis, Objetos etc)."
Por exemplo, em JavaScritpt podemos criar um literal para uma expressão regular:
var regex = /.../; // Literal (o resultado já é um objeto RegExp)
Acima temos uma expressão regular em uma variável, ou seja, o resultado já é um objeto RegExp.
Agora observe essa mesma funcionalidade sem utilizar literal:
var regex = new RegExp("..."); //comando "new" para se construir o objeto
Veja que usamos o comando "new" para se construir um objeto. Isso se extende quando você precisa usar uma String, uma classe etc...
Sim, este último foi bem parecido com o Java...
Lambda no Java 8
No Java 8, podemos ter um literal para uma expressão lambda que consiste em uma lista de argumentos (zero ou mais) seguida de um operador (->
) e logo em seguida a expressão que deve produzir um valor. Vejamos alguns exemplos:
() -> 69 // Não recebe nada e sempre retorna "69"
x -> x*x // Recebe algo e retorna seu quadrado
(x,y) -> x + y // Recebe dois valores e retorna sua soma
(int x, int y) -> x+y
(x, y) -> { return x+y; }
(int x, int y) -> { System.out.println(x+y); return x+y; }
Ainda não ficou claro? Vamos pegar um código que talvez você se familiarize:
List<String> lista = Arrays.asList("Java", "Lambda", "Lambda Expression");
Temos uma lista de String
simples e queremos ordena-la pelo menor tamanho. E como faríamos isso em Java? Bem podemos criar uma classe e nela implementar o Comparator
e passá-la como parâmetro no sort
ou para não criarmos uma classe só para isso, podemos usar uma classe anônima, mais ou menos assim...
Collections.sort(lista, new Comparator<String>(){
public int compare(String valor1, String valor2){
return valor1.length() - valor2.length();
}
});
Criamos uma lista e estamos usando o sort
da Collections
passando a lista que queremos ordenar e um Comparator
onde usamos uma classe anônima com a implementação do compare
, ele recebe dois valores e na implementação é saber quem é o menor, simples.
Agora utilizando os conceitos de Lambda Expression, iremos fazer o mesmo código:
Collections.sort(lista, (v1, v2) -> v1.length() - v2.length());
Incrível neh? É a mesma funcionalidade. Agora feche a boca... e observe essa sentença:
(v1, v2) -> v1.length() - v2.length()
Vamos fazer um comparativo rápido aqui:
Lambda: (v1,v2) / Java: int compare(String valor1, String valor2)
Lambda: v1.length() - v2.length() / Java: return valor1.length() - valor2.length();
No lugar de criar uma classe anônima, passamos uma Expressão Lambda como argumento, evitando assim a construção de uma classe (classe anônima).
Basicamente a introdução de expressões lambda no Java não torna as funções em funções primeira-classe, isso porque essas expressões são convertidas em classes anônimas pelo compilador (observe que por causa disso também será possível fazer referência direta a um método java e indireta através do objeto que o define), mas na prática evita que você tenha que criar essas classes anônimas de apenas um único método, é isso que as expressões lambda fazem.
Conclusão
Vimos aqui apenas um pequeno resumo do que de fato são as expressões Lambda no Java e as várias possibilidades que podemos ter com a linguagem, possibilidades essas que iremos em breve falar mais sobre o assunto aqui.
E a principal vantagem disso é a concisão - fazer mais coisas escrevendo menos e com frequência não existe razão para se exigir que uma função esteja sempre acompanhada de uma classe e usando essas expressões evita muitas construções desnecessárias, porém, para quem está acostumado com a sintaxe do Java poderá sim ter alguma dificuldade para se acostumar e até entender. Isso pode e vai caso você não tenha conhecimento no conceito, prejudicar e dificultar o entendimento do código, já que houve uma grande mudança na estrutura da linguagem por assim dizer. Por isso é importante você entender esse conceito antes de querer sair "migrando" seu código e colocando Lambda em tudo.
Mas que magia negra foi essa? Como uma linguagem tipada como o Java pode implementar isso? Bem, isso deixaremos para um próximo post aqui no blog, enquanto isso já pode ir entendendo melhor o Lambda na sua documentação oficial e se quiser saber mais sobre Expressão Lambda aconselho a ler esse documento ou se preferir este. Lembre-se que se você entender como funciona o Lambda "puro"vai ser muito fácil você implementar esse conceito no Java ;).
Então o que achou? Já está usando Lambda nos seus projetos? Deixe seu comentário aqui ;)
You might also be interested in these articles...
Desenvolvedor, Fundador da TriadWorks e da JavaCE
Posted in: boa praticacodigocursoensinoexpressaofortalezajava8javascriptjeelambdaliteraislogica de programacaoprimeira classetreinamentotriadworkstutorial