DEV Community

Cover image for Lambdas and functional programming - Java 11
Joao Carlos Sousa do Vale
Joao Carlos Sousa do Vale

Posted on

Lambdas and functional programming - Java 11

Lambdas and Functional Interfaces

Writing Simple Lambdas

  • Functional programming is a way of writing code more declaratively. You specify what you want to do rather than dealing with the state of objects. You focus more on expressions than loops.
  • Functional programming uses lambda expressions to write code.
  • Lambda expression is an unnamed method.

LAMBDA EXAMPLE

public class Animal {

   private String especie;
   private boolean podeSaltar;
   private boolean podeNadar;

   public Animal(String nomeDaEspecie, boolean saltador, boolean nadador){
      especie = nomeDaEspecie;
      podeSaltar = saltador;
      podeNadar = nadador;
   }

   public boolean podeSaltar() { return podeSaltar; }
   public boolean podeNadar() { return podeNadar; }
   public String toString() { return especie; }
}
Enter fullscreen mode Exit fullscreen mode
public interface AnalisadorDeAnimal {
   boolean teste(Animal a);
}
Enter fullscreen mode Exit fullscreen mode
import java.util.ArrayList;
import java.util.List;

public class TraditionalSearch {
    public static void main(String[] args) {

        // lista de animais
        List<Animal> animais = new ArrayList<Animal>();
        animais.add(new Animal("peixe", false, true));
        animais.add(new Animal("canguru", true, false));
        animais.add(new Animal("coelho", true, false));
        animais.add(new Animal("tartaruga", false, true));

        // imprime os animais verificados
        imprimir(animais, new VerificaSeSaltador());
    }
    private static void imprimir(List<Animal> animais, Verificador verificador) {
        for (Animal animal : animais) {
            // verificando
            if (verificador.verificar(animal)) {
                System.out.print(animal + " ");
            }
        }
        System.out.println();
    }
}
Enter fullscreen mode Exit fullscreen mode
canguru coelho
Enter fullscreen mode Exit fullscreen mode
  • what if we want to verify if the animal can swin?
  • alternative: lambdas
// imprime os animais que podem saltar  
imprimir(animais, animal -> animal.podeSaltar());
Enter fullscreen mode Exit fullscreen mode

or

// imprime os animais que podem nadar  
imprimir(animais, animal -> animal.podeNadar());
Enter fullscreen mode Exit fullscreen mode

Lambda Syntax

  • Lambdas work with interfaces that have only one abstract method.
    animal -> animal.podeSaltar()
Enter fullscreen mode Exit fullscreen mode
  • syntax:
    • a single parameter (animal)
    • the arrow to separate the parameter and body;
    • a body that calls a single method and returns the result of that method
(Animal animal) -> {return a.podeSaltar();}
Enter fullscreen mode Exit fullscreen mode
  • syntax
    • A single parameter specified with the name animal and stating the type is Animal
    • The arrow operator to separate the parameter and body
    • A body that has one or more lines of code, including a semicolon and a return statement
  • The parentheses can be omitted only if there is a single parameter;
  • Type is not explicitly stated;
  • we can omit braces when we have only a single statement.
    • Java doesn’t require you to type return or use a semicolon when no braces are used.

Introducing Functional Interfaces

  • functional interfaces are interfaces that have only one abstract method;
  • you should know the following built-in functional interfaces: Predicate, Consumer, Supplier, and Comparator;

PREDICATE

public interface Predicate<T> {
   boolean test(T t);
}
Enter fullscreen mode Exit fullscreen mode
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class UsoDoPredicate {

    public static void main(String[] args) {
        List<Animal> animais = new ArrayList<>();
        animais.add(new Animal("peixe", false, true));
        animais.add(new Animal("canguru", true, false));

        print(animais, a -> a.podeSaltar());
    }
    private static void print(List<Animal> animais, Predicate<Animal> verificador) {
        for (Animal animal : animais) {
            if (verificador.test(animal))
                System.out.print(animal + " ");
        }
        System.out.println();
    }
}
Enter fullscreen mode Exit fullscreen mode
canguru
Enter fullscreen mode Exit fullscreen mode

CONSUMER

public interface Consumer<T> {
    void accept(T t)
}
Enter fullscreen mode Exit fullscreen mode
import java.util.function.Consumer;

public class UsoDoConsumer {

    public static void main(String[] args) {
        Consumer<String> consumer = x -> System.out.println(x);
        print(consumer, "Hello World");
    }
    private static void print(Consumer<String> consumer, String value) {
        consumer.accept(value);
    }
}
Enter fullscreen mode Exit fullscreen mode
Hello World
Enter fullscreen mode Exit fullscreen mode

SUPPLIER

public interface Supplier<T> {  
     T get();  
}
Enter fullscreen mode Exit fullscreen mode
import java.util.function.Supplier;

public class UsoDoSupplier {

    public static void main(String[] args) {
        Supplier<Integer> number = () ->  42;
        System.out.println(returnNumber(number));
    }

    private static int returnNumber(Supplier<Integer> supplier) {
        return supplier.get();
    }
}
Enter fullscreen mode Exit fullscreen mode
42
Enter fullscreen mode Exit fullscreen mode

COMPARATOR

  • rules, if returns:
    • a negative number means the first value is smaller;
    • zero means they are equal,
    • and a positive number means the first value is bigger.
import java.util.Arrays;
import java.util.Comparator;

public class UsoDoComparator {

    public static void main(String[] args) {
        Integer [] array = {4, 1, 7, 2, 5};
        print(array, (i1, i2) -> i1 - i2);
    }

    public static void print(Integer [] array, Comparator<Integer> comparator) {
        Arrays.sort(array, comparator);
        System.out.println(Arrays.toString(array));
    }
}
Enter fullscreen mode Exit fullscreen mode
[1, 2, 4, 5, 7]
Enter fullscreen mode Exit fullscreen mode

Working with Variables in Lambdas

  • places can appear:
    • parameter list;
    • local variables declared inside the lambda body;
    • variables referenced from the lambda body;
  • Method parameters and local variables are allowed to be referenced if they are effectively final (the value of a variable doesn’t change after it is set).

Calling APIs with Lambdas

import java.util.ArrayList;
import java.util.List;

public class ExemploUsandoLambdasEmAPI {

    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Joao");
        names.add("Jose");
        names.add("Maria");
        System.out.println("Nomes: " + names);

        names.removeIf(name -> !name.startsWith("J"));
        System.out.println("Nomes iniciando com J: " + names);

        names.add("Araci");
        names.add("Ze");
        System.out.println("\nNomes: " + names);

        names.sort((name1, name2) -> name1.compareTo(name2));
        System.out.println("Nomes ordenados: " + names);

        System.out.println("\nImprimindo novamente");
        names.forEach(name -> System.out.println(name));

    }
}
Enter fullscreen mode Exit fullscreen mode
Nomes: [Joao, Jose, Maria]
Nomes iniciando com J: [Joao, Jose]

Nomes: [Joao, Jose, Araci, Ze]
Nomes ordenados: [Araci, Joao, Jose, Ze]

Imprimindo novamente
Araci
Joao
Jose
Ze
Enter fullscreen mode Exit fullscreen mode

REMOVEIF()

  • takes a Predicate to decide what to remove from the list.

SORT()

  • The sort() method takes Comparator that provides the sort order.

FOREACH()

  • It takes a Consumer and calls that lambda for each element encountered.

Top comments (0)