- Introdução às Expressões Lambda
As expressões lambda foram uma atualização significativa no JDK 1.8, marcando o reconhecimento por parte da linguagem Java do paradigma de programação funcional e sua integração gradual.
Um dos conceitos centrais da programação funcional é a capacidade de tratar funções como cidadãos de prmieira classe — ou seja, permitir que funções sejam passadas como argumentos para outras funções e até mesmo retornadas como resultado.
- Interfaces Funcionais
Uma "interface funcional" é aquela que contém exatamente um único método abstrato. Cada expressão lambda definida para esse tipo de interface será automaticamente associada a esse único método.
O Java 8 introduziu a anotação @FunctionalInterface para marcar explicitamente essas interfaces. Caso a interface não siga as regras específicas de uma interface funcional, o compilador lançará um erro.
- A Enotação @FunctionalInterface
/*
* Esta anotação indica que a interface é intencionalmente funcional,
* conforme definido pela especificação da linguagem Java.
*
* Conceitualmente, uma interface funcional possui exatamente um método abstrato.
*
* Se uma interface declarar um método herdado de java.lang.Object, ele não conta
* como método abstrato, já que qualquer implementação herda esses métodos.
*/
- Exemplos Práticos
package com.skd.lambda;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ExemploLambda {
public static String[] elementos = new String[]{"um", "dois", "tres"};
public static void main(String[] args) {
criarThread();
ordenarLista();
usarLambdaSemParametros();
usarLambdaComTipos();
}
/**
* Criação de threads usando lambda
*/
public static void criarThread() {
final int contador = 0;
// Forma tradicional com implementação direta
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Forma tradicional: contador=" + contador);
}
}).start();
// Usando lambda sem especificar tipos de parâmetros
new Thread(() -> System.out.println("Lambda sem tipos: contador=" + contador)).start();
// Usando lambda com especificação de tipo
new Thread((Runnable) () -> {
System.out.println("Lambda com tipos: contador=" + contador);
}).start();
}
/**
* Ordenação de lista usando a antiga forma
*/
public static void ordenarLista() {
List<String> lista = Arrays.asList(elementos);
Collections.sort(lista, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s2.compareTo(s1);
}
});
for (String item : lista) {
System.out.println(item);
}
}
/**
* Usando lambda para ordenação sem necessidade de especificar tipos
*/
public static void usarLambdaSemParametros() {
List<String> lista = Arrays.asList(elementos);
Collections.sort(lista, (x, y) -> y.compareTo(x));
for (String item : lista) {
System.out.println(item);
}
}
/**
* Usando lambda com declaração explícita de tipos
*/
public static void usarLambdaComTipos() {
List<String> lista = Arrays.asList(elementos);
Collections.sort(lista, (Comparator<? super String>) (String x, String y) -> {
return y.compareTo(x);
});
for (String item : lista) {
System.out.println(item);
}
}
}