Você sabe o que são Expressões Lambdas (Lambda Expressions)? As Expressões Lambda, introduzidas no Java 8, permitem que você trate "comportamento" como se fosse um dado.
Segunda a Java Language Specification: As expressões lambda são estruturas semelhantes a métodos que fornecem uma lista de parâmetros formais e um corpo (que pode ser uma expressão ou um bloco de código) expressos em termos desses parâmetros
Antes do Java 8, se você quisesse passar um pedaço de código para ser executado (ex: num clique de botão ou numa Thread), você precisava criar uma Classe Anônima.
Jeito velho:
// Criando uma Thread antiga
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Executando tarefa...");
}
}).start();
Jeito novo:
// "() ->" significa: Sem argumentos, execute isso.
new Thread(() -> System.out.println("Executando tarefa...")).start();
- O principal objetivo de uma expressão lambda é produzir uma instância de uma interface funcional (uma interface que possui exatamente um método abstrato).
- Elas oferecem uma sintaxe muito mais concisa do que as declarações de classes anônimas.
### Sintaxe e estrutura
Uma expressão lambda é composta de três partes. Pense nela como uma função sem nome.
A sintaxe básica é composta por:
(Parâmetros) -> { Corpo }. Sem parâmetros:
() -> System.out.println("Oi");Um parâmetro:
(s) -> System.out.println(s);(Pode omitir parênteses se for só um).Múltiplos parâmetros: Devem estar entre parênteses. Exemplo:
(x, y) -> x + y.Parâmetros não nomeados: É possível usar o caractere
_(underscore) para declarar um parâmetro cujo valor não será utilizado no corpo da lambda.Com retorno:
(a, b) -> { return a + b; }Simplificado:
(a, b) -> a + b(Se só tiver uma linha, não precisa de{}nem da palavrareturn).
Você pode declarar os tipos dos parâmetros (exclusivamente para todos ou nenhum) ou deixar que o compilador os infira a partir do contexto da interface funcional.
Regras de Uso e Contexto
Onde usar: Devem ocorrer apenas em contextos de atribuição, de invocação (como argumentos de métodos) ou de cast (conversão explícita). O Java só permite Lambda quando o tipo esperado é uma Interface Funcional.
Captura de Variáveis: Uma lambda pode acessar variáveis locais do escopo ao seu redor, desde que essas variáveis sejam finais ou efetivamente finais (ou seja, seu valor nunca mude após a inicialização).
Exemplo prático
List<String> nomes = Arrays.asList("Ana", "Pedro", "Ze", "Maria");
// Jeito Antigo (Classe Anônima)
Collections.sort(nomes, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
// Jeito Novo
// O Java sabe que s1 e s2 são Strings (Inferência de Tipo)
Collections.sort(nomes, (s1, s2) -> Integer.compare(s1.length(), s2.length()));
Method Reference
Muitas vezes, uma expressão Lambda não faz nada além de chamar um método que já existe, você pode deixar o código ainda mais limpo usando o operador "quatro pontos" (::).
Por exemplo: s -> System.out.println(s). Perceba que o parâmetro s é apenas repassado para o método println. Não há lógica adicional.
Exemplos:
// Lambda: numero -> Math.abs(numero)
Function<Integer, Integer> valorAbsoluto = Math::abs;
// O objeto 'System.out' já existe.
// Lambda: s -> System.out.println(s)
Consumer<String> impressora = System.out::println;
// Aqui, o método toUpperCase é chamado NA instância da String passada
// Lambda: s -> s.toUpperCase()
Function<String, String> maiuscula = String::toUpperCase;
// Exemplo composto:
List<String> nomes = Arrays.asList("java", "python", "c");
// A String "java" chama o método compareTo passando "python"
nomes.sort(String::compareTo);
// Lambda: () -> new String()
Supplier<String> novaString = String::new;
Top comments (0)