Expressões Lambda

  1. 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.

  1. 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.

  1. 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.
 */

  1. 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);
        }
    }
}

Tags: java lambdas funções Interfaces Funcionais Programação Funcional

Publicado em 8-4 18:01