Lambda é um recurso muito esperado na linguagem java sendo implementado na versão 8 e já presente nas linguagens funcionais há certo tempo. Ele deve alterar como utilizamos a linguagem, pois é bastante comum ao utilizarmos uma API, termos de implementar uma interface com uma classe anônima que possui somente um método, geralmente o que queremos fazer é passar um método para um objeto para ele ser executado em certo momento, e a forma como fazemos acaba sendo um pouco burocrática.

Para começar, vamos a um exemplo clássico, ordenar uma lista objetos com um comparador. Se implementarmos em nosso objeto a interface Comparable resolveria o problema, mas se necessitássemos alterar os critérios de ordenação em tempo de execução teremos que criar um objeto que implementa Comparator e passá-lo para o método sort de List(agora List tem um método sort com uma implementação “default” para não quebrar a compatibilidade, recurso novo também).

public class Produto{
 
    private String nome;
    private double valor;
 
    public Produto(String nome, double valor){
        this.nome = nome;
        this.valor = valor;
    }
 
    public String getNome(){
        return this.nome;
    }
    public double getValor(){
        return this.valor;
    }
 
}

Um código para ordenar uma lista de objetos Produto

public class MainProduto{
 
    public static void main(String args[]){
 
        List<Produto> produtos = new ArrayList<Produto>();
        produtos.add( new Produto("Paçoquinha" , 2.80) );
        produtos.add( new Produto("Refrigerante" , 5.50) );
        produtos.add( new Produto("Bala" , 0.25) );
 
        produtos.sort( new Comparator<Produto>(){
            public int compare(Produto p1 ,Produto p2){
                return Double.compare( p1.getValor() , p2.getValor() );
            }
        });
 
        for(Produto p : produtos){
            System.out.println( p.getNome()+" - "+p.getValor() );
        }
 
    }
     
}

Agora implementando através do Lambda.

public static void main(String args[]){
 
    List<Produto> produtos = new ArrayList<Produto>();
    produtos.add( new Produto("Paçoquinha" , 2.80) );
    produtos.add( new Produto("Refrigerante" , 5.50) );
    produtos.add( new Produto("Bala" , 0.25) );
 
    produtos.sort( (p1 , p2) -> Double.compare(p1.getValor() , p2.getValor() ) );
 
    produtos.forEach( (p) -> System.out.println( p.getNome()+" - "+p.getValor() ) );
 
}

Na linha 8, utilizamos o lambda, que funciona com uma interface funcional. Uma interface funcional é aquela que possui um único método abstrato. Como ele possui um único método o compilador consegue descobrir qual método está sendo chamado e seus parâmetros( valores passados dentro dos parênteses antes do sinal “->” ) e a implementação ou seja o que vem depois do “->“, que pode ter uma ou várias linhas, se tiver várias linhas elas devem estar entre {chaves} e se a interface que estamos implementando tiver retorno devemos utilizar o comando return o que se tiver um único comando o compilador consegue utilizar o resultado deste como retorno.

Na linha 10 também temos uma novidade, para percorrer um List podemos utilizar o novo método forEach que recebe como parâmetro um objeto da interface funcional java.util.function.Consumer, uma interface das novas interfaces do pacote java.util.function. O Consumer possui um método accept, que recebe um parâmetro e executa uma operação.

Vamos a outro exemplo bem comum, um Listener.

public static void main(String args[]){
 
    JFrame janela = new JFrame();
    janela.setSize(400,400);
         
    final JTextField text = new JTextField(30);
    JButton bt = new JButton("Botão");
 
    bt.addActionListener( (e) -> {
        String campo = text.getText();
        JOptionPane.showMessageDialog(null , "Campo: "+campo);
    });
 
    janela.setLayout( new FlowLayout() );
    janela.add(text);
    janela.add(bt);
    janela.setVisible(true);
 
}

Na linha 9 implementamos o ActionListener através de um Lambda.

Mais um exemplo.

public static void main(String args[]){
 
    new Thread( () -> {
        while( true ){
            System.out.println("Rodando....");
        }
    }).start();     
 
}

Interfaces Funcionais

Uma interface funcional como vimos anteriormente é simplesmente uma interface que declara somente um método abstrato, como vimos nos exemplos anteriores várias interfaces já existente no Java podem ser consideradas interfaces funcionais. Para criar uma interface funcional não é necessário qualquer tipo de palavra chave, embora pode-se adicionar a anotação @FunctionalInterface que serve somente para forçar a validação em tempo de compilação que a interface tenha somente um método. Vamos a um exemplo.

@FunctionalInterface
interface Validador<T> {
 
    boolean validar(T valor);
 
}

Agora basta utilizar um lambda para criar um validador, e utilizar em diversos valores.

public static void main(String args[]){
 
    Validador<String> validadorCEP = (s) -> s.matches("[0-9]{5}-[0-9]{3}");
         
    System.out.println( validadorCEP.validar("97501-570"));
    System.out.println( validadorCEP.validar("33-3333") );
}

Era isso e desculpem pela piada do titulo, não resisti.