Java - Lambdas
Published: 2020-10-09 10:18:48

Lambdas são funções não declaradas, ou seja, que não precisam ser declaradas para serem utilizadas, sendo desnecessário declarar um nome, parametros, modificadores de acesso e retorno. Também podemos dizer que uma lambda é uma forma mais simples de implementar um interface que só tem um único método.

Básicamente, as funções lambdas, no Java, tem a sintaxe:
(args)->(corpo).
Exemplos:

```
(int x, int y) -> { return x * y; }
Aluno exibicao = (Pessoa p)-> { System.out.println(p.idade); }
() -> System.out.println(new Date());
() -> { return 25.789; }
x -> x < 100;
```
As chaves só são obrigatórias quando o corpo da função tiver mais de um comando.
Por exemplo:

```
(int x, int y) -> { return x * y; }
```
Pode ser escrito:

```
(int x, int y) -> return x * y;
```
Obtendo o mesmo resultado.

As funções podem ou não ter parâmetros, e os tipos podem ser omitidos, assim o Java vai inferir o tipo.

Exemplo:

Função com parâmetros (e com o tipo declarado!).
```
(int x, int y) -> { return x * y; }
```
Função com parâmetros, sem o tipo declarado.

```
(x, y) -> { return x * y; }
```
Função sem parâmetro.
```
() -> System.out.println(new Date());
```
Sem o return, o tipo da função é inferido como void.

```
(a) -> this.x = a;
```
É importante ressaltar que a lambda é diferente do uso de classes anônimas, observável pelos .class gerados. Observará que não terá gerado diversos .class que seriam comumente gerados caso utilizasse-mos, para cada classe anônima utilizada.

Aplicações:

###Threads

Nas threads elas são utilizadas para simplificação do código, tornando menos verboso.
```
/*
* Implementação da interface Runnable seguido da criação 
* da thread com a implementação
*/
Runnable e = new Runnable(){
      public void run(){
           System.out.println(new Date());
      }
};
new Thread(e).start();

/*
* A mesma implementação, agora utilizando expressão 
* lambda
*/
Runnable e = () -> System.out.println(new Date());
new Thread(e).start();

/*
* Ainda pode ser mais simplificada!!
*/
new Thread(
() -> System.out.println(new Date())
).start();
```
###Coleções

Nas Coleções flexibilização de funções de ordenação e filtros, por exemplo.

```
/*
* Imprimir todos os elementos de uma lista
*/
List l = Arrays.asList("João", "Ana", "Maria", "Cesar");
for(String s: l){
    System.out.println(s);
}

/*
* Agora utilizando lambda
*/
List l = Arrays.asList("João", "Ana", "Maria", "Cesar");
l.forEach(s -> System.out.println(s));

/*
* Lambda com mais de um comando
*/
List l = Arrays.asList("João", "Ana", "Maria", "Cesar");
l.forEach(s -> {
   if(StringUtils.equals("Cesar"){
       System.out.println(a);
  }
});

/*
* Ordenamento "convencional"
*/
List l = Arrays.asList("João", "Ana", "Maria", "Cesar");
Collections.sort(l, new Comparator(){
    @Override
    public int compare(String s1, String s2){
       return s1.compareTo(s2);
    }
});
l.forEach(p -> System.ou.println(p));

/*
* Ordenamento usando lambda
*/
List l = Arrays.asList("João", "Ana", "Maria", "Cesar");
Collections.sort(l, (String s1, String s2) -> s1.compareTo(s2));
l.forEach(p -> System.ou.println(p));
```
###Listeners

Nos Listners usada para simplificação de código.
**Listners são classes que implementam o Design Pattern Observer**
```
/*
* "Ouvindo" uma ação em um botão em uma janela Swing
*/
botton.addActionListner(new ActionListner(){
    @Oberride
    public void actonPerformed(ActionEvent e){
        System.out.println("Algumas ações...");
    }
});

/*
* A mesma solução usando lambda
*/
button.addActionListner( (e) -> {
    System.out.println("Algumas ações...");
});
```
###Funções Genéricas

Nas Funções genéricas utilizado para criar funções genéricas utilizadas para solução de problemas, quando as funções aceitam expressões lambdas como parâmetro.
```
public class Principal{
   /*
   * um método que testa uma condição
   */
   public static void testaExpressao(List l, Predicate p){
       l.forEach(n -> {
          if(p.test(n)){
             System.out.println(n);
          }
       });
   }

   /*
   * chamando com lambda
   */
   public void mai(String[] args){
      List l = Arrays.asList("João", "Ana", "Maria", "Cesar");
      //Imprime o nome do "Cesar", se existir
      testaExpressao(l, (n) -> StringUtils.equals("Cesar"));
      //Imprime toda a lista
      testaExpressao(l, (n) -> true);
      //Não imprime nada
      testaExpressao(l, (n) -> false);
   }
}
```