Java 8: Entenda facilmente funções lambda, a principal novidade!
Tags: java, java8, lambda, programacaofuncional
Published: 2019-03-24 16:39:18

---
title: Java 8: Entenda facilmente funções lambda, a principal novidade!
published: true
tags: Java,Java 8,Lambda,ProgramacaoFuncional
canonical_url: https://rinaldo.dev/java-8-entenda-facilmente-funcoes-lambda-a-principal-novidade/
cover_image: https://rinaldo.dev/wp-content/uploads/2019/03/STATIONERY-3.png
---

A criação de **Funções Lambda** foi a principal novidade do **Java 8**, lançado em **2014**! Hoje é praticamente obrigatório conhecer como elas funcionam e saber utilizá-las no seu código.

[Prefere esse conteúdo em vídeo? Assista aqui!](https://www.youtube.com/watch?v=lbCYLgoVpfQ&)

### Java 8 e programação funcional

Há algum tempo o JavaScript veio se estabelecendo como a linguagem padrão de desenvolvimento _front-end_. Ao mesmo tempo ocorre também o aparecimento e a popularização de linguagens como Scala, Kotlin e Python. Junto desses movimentos, a programação funcional começou a se tornar cada vez mais popular.

Com a intenção de trazer essa possibilidade também para o Java, foi criada a nova sintaxe de **funções lambda**. Se você nunca viu uma, aqui está:

```java
() -> System.out.println("Hello World")
```

Se você nunca viu um código assim, não se assuste, você vai entender facilmente o que significa.

* * *

### Java sem funções lambda

Se você programa Java há algum tempo, provavelmente já teve que escrever algum código parecido com esse:

```java
public static void main(String[] args) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello World");
        }
    }).run();
}
```

Apesar de esse código funcionar perfeitamente, ele tem um grande problema: é **gigante**. Pense bem, foram necessárias 6 linhas de código para criar uma Thread e imprimir “Hello World”, algo que deveria ser completamente trivial. Agora, veja esse mesmo código utilizando uma função lambda:

```java
public static void main(String[] args) {
    new Thread(() -> System.out.println("Hello World")).run();
}
```

O código acima é interpretado pelo compilador exatamente igual ao anterior, tendo uma única linha de código e sendo muito mais conciso. E o mais interessante aqui é que ainda estamos utilizando **o mesmo**  **construtor** para criar uma `Thread`. A própria IDE confirma isso:

![Java 8: Screenshot do Eclipse mostrando o construtor da classe Thread recebendo uma instância da interface Runnable.](https://rinaldo.dev/wp-content/uploads/2019/03/runnable-1.png)<figcaption>Construtor recebendo uma instância de <code>Runnable</code></figcaption>

O compilador sabe que essa função lambda é uma instância de `Runnable`, mesmo que nós não deixemos isso explícito. Ok, mas como ele sabe disso?

* * *

### Java 8 e o conceito SAM

Esse comportamento do compilador fica simples quando entendemos o conceito de **Single Abstract Method**, ou **SAM**. Basicamente, qualquer interface que tenha um único método está seguindo esse conceito. Logo, o compilador entende que sua função lambda é, na verdade, a implementação desse único método. Vamos ver de perto.

A interface `Runnable`, por exemplo, possui apenas o método `run`. Aqui está ela, copiada direto da JDK:

```java
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}
```

Sendo assim, ao utilizar uma função lambda como fizemos acima, o compilador entende que ela só pode ser a implementação do método `run`.

Quanto à anotação `@FunctionalInterface` presente nessa classe, ela é apenas **informativa**. Ela instrui ao compilador que gere um **erro** caso essa classe não preencha todos os requisitos para ser uma **interface funcional**, ou seja, uma que pode ser criada a partir de uma função lambda. Por exemplo, se essa interface tivesse **dois métodos**, ocorreria um erro de compilação. Apesar disso, essa anotação **não** é obrigatória. Você pode utilizar funções lambda com qualquer interface que atenda os **pré-requisitos** para ser considerada funcional.

Ok, então funções lambda servem apenas para eu diminuir a quantidade de linhas de código em casos como esse? **Não**. A verdade é que as funções lambda são muito mais **úteis** do que parecem. Os exemplos que dei acima são apenas para **entender** seu funcionamento, mas o que elas permitem fazer em Java é muito mais **interessante**.

* * *

### Programação funcional

Com funções lambda é possível utilizar métodos muito conhecidos para quem utiliza **JavaScript**, como `filter`, `map` e `forEach`.

Imagine, por **exemplo**, que você tem uma lista de números. Você deseja imprimir o valor dos 7 primeiros, multiplicado por 2, mas apenas se o número for par. Vejamos uma implementação possível com Java tradicional:

```java
public static void main(String[] args) {
    List<Integer> lista = Arrays.asList(1,5,8,7,4,6,3,2,1,8,5,7,4);
    for (int i = 0; i < 7; i++) {
        Integer numero = lista.get(i);
        if (numero % 2 == 0) {
            System.out.println(numero * 2);
        }
    }
}
```

Essa é uma implementação comum, funciona perfeitamente e, se você programa em Java há algum tempo, provavelmente está acostumado a vê-la. Porém, vamos ver como seria a mesma implementação com o uso de **Streams** do **Java 8**:

```java
public static void main(String[] args) {
    List<Integer> lista = Arrays.asList(1,5,8,7,4,6,3,2,1,8,5,7,4);
    lista.stream()
        .limit(7)
        .filter(e -> e % 2 == 0)
        .map(e -> e * 2)
        .forEach(System.out::println);
}
```

Para quem não está acostumado, essa implementação pode parecer estranha a primeira vez. Porém, ela é muito mais **concisa** e **delimitada**. É possível saber **exatamente** todas as operações que estão sendo feitas nessa lista. Claramente existe um limite (`limit`), um filtro (`filter`), uma transformação (`map`) e uma ação para cada item (`forEach`).

Essa é estrutura da função lambda passada para o método `filter`:

![Java 8: estrutura da função lambda. Primeiro temos os parâmetros da função, depois o arrow token "->", depois do corpo da função.](https://rinaldo.dev/wp-content/uploads/2019/03/explicacao_lambda_lambdas.png)<figcaption>Estrutura da função lambda passada no método <code>filter</code></figcaption>

A partir do momento que você aprende funções lambda e a nova API de Streams, você escreve um código muito **mais fácil** de entender, logo, mais fácil de dar manutenção. Além disso, muito **menos** propício a **bugs**.

* * *

### A real vantagem do Java 8

De fato, a principal vantagem das funções lambdas no Java 8 foi permitir o uso de **Streams**. Sem elas seria praticamente impossível utilizar Streams com facilidade. O código seria tão grande e complicado, que simplesmente não seria útil. Se você está curioso para saber como ficaria a implementação acima sem o uso de funções lambda, aqui está. Por favor, nunca faça isso.

```java
public static void main(String[] args) {
    List<Integer> lista = Arrays.asList(1, 5, 8, 7, 4, 6, 3, 2, 1, 8, 5, 7, 4);
    Stream<Integer> limit = lista.stream().limit(7);
    // nunca escreva um código assim!
    Stream<Integer> filter = limit.filter(new Predicate<Integer>() {
        @Override
        public boolean test(Integer e) {
            return e % 2 == 0;
        }
    });
    Stream<Integer> map = filter.map(new Function<Integer, Integer>() {
        @Override
        public Integer apply(Integer e) {
            return e * 2;
        }
    });
    map.forEach(new Consumer<Integer>() {
        @Override
        public void accept(Integer t) {
            System.out.println(t);
        }
    });
}
```

* * *

### Um caminho para o futuro do Java

Apesar de funções lambda terem sido extremamente úteis para o lançamento da API de Streams, isso foi apenas o começo. Várias **APIs** estão se tornando possíveis com o uso de **funções lambda**. O Java 9, por **exemplo**, trouxe [Reactive Streams](http://www.reactive-streams.org), o padrão implementado pela famosa biblioteca [RxJava](https://github.com/ReactiveX/RxJava).

**Em breve** provavelmente estaremos implementando muitas coisas com programação funcional e funções lambdas no **Java**, como requisições **HTTP**, operações com **arquivos** e comunicação com **banco de dados**.

Quer saber um pouco mais da utilidade de funções lambda? [Veja esse outro artigo sobre **Streams** e como utilizar funções lambda com coleções.](https://dev.to/rinaldodev/java-8-streams-pare-de-usar-for-e-simplifique-seu-codigo-4df8)

**Parabéns**! Agora **você** conhece expressões lambda do Java 8, e pode utilizar esse conhecimento para entregar **seu** projeto mais **rápido** e **crescer** na **sua** carreira.

[Quer acessar esse conteúdo em vídeo também? Assista aqui!](https://www.youtube.com/watch?v=lbCYLgoVpfQ&)

Quer receber minhas **melhores dicas** para escrever código de **alta qualidade** e entregar projetos no prazo? [**Então acesse aqui**.](https://rinaldo.dev/contato/)

Quer aprender a melhorar seu código diariamente? Então me segue no **twitter**: [**https://twitter.com/rinaldodev**](https://twitter.com/rinaldodev)

* * *

**Você** já viu algum código com funções lambda recentemente? Ou conhece outras situações em que poderíamos utilizar? Deixe um comentário! Compartilhe também!

Gostou do que aprendeu? Compartilhe com outros Devs!

O post [Java 8: Entenda facilmente funções lambda, a principal novidade!](https://rinaldo.dev/java-8-entenda-facilmente-funcoes-lambda-a-principal-novidade/) apareceu primeiro em [rinaldo.dev](https://rinaldo.dev).