Лямбды и функциональное программирование — Java 11


Лямбды и функциональные интерфейсы

Написание простых ламбдас

  • Функциональное программирование — это способ писать код более декларативно. Вы указываете, что вы хотите сделать, а не работаете с состоянием объектов. Вы больше внимания уделяете выражениям, чем циклам.
  • В функциональном программировании для написания кода используются лямбда-выражения.
  • Лямбда-выражение — это неименованный метод.

ПРИМЕР ЛЯМБДА-ВЫРАЖЕНИЯ

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; }
}
Вход в полноэкранный режим Выход из полноэкранного режима
public interface AnalisadorDeAnimal {
   boolean teste(Animal a);
}
Войти в полноэкранный режим Выход из полноэкранного режима
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();
    }
}
Войти в полноэкранный режим Выход из полноэкранного режима
canguru coelho
Войти в полноэкранный режим Выйти из полноэкранного режима
  • что если мы хотим проверить, умеет ли животное плавать?
  • альтернатива: ламбды
// imprime os animais que podem saltar  
imprimir(animais, animal -> animal.podeSaltar());
Войти в полноэкранный режим Выйти из полноэкранного режима

или

// imprime os animais que podem nadar  
imprimir(animais, animal -> animal.podeNadar());
Войти в полноэкранный режим Выйти из полноэкранного режима

Синтаксис лямбды

  • Лямбды работают с интерфейсами, которые имеют только один абстрактный метод.
    animal -> animal.podeSaltar()
Войти в полноэкранный режим Выйти из полноэкранного режима
  • синтаксис:
    • один параметр (животное)
    • стрелка для разделения параметра и тела;
    • тело, вызывающее один метод и возвращающее результат этого метода
(Animal animal) -> {return a.podeSaltar();}
Вход в полноэкранный режим Выйти из полноэкранного режима
  • синтаксис
    • Одиночный параметр, заданный именем animal и указывающий тип Animal
    • Оператор стрелки для разделения параметра и тела
    • Тело, содержащее одну или несколько строк кода, включая точку с запятой и оператор возврата.
  • Круглые скобки могут быть опущены только в случае единственного параметра;
  • тип не указан явно;
  • скобки можно опустить, если есть только одно утверждение.
    • Java не требует вводить return или использовать точку с запятой, когда скобки не используются.

Представление функциональных интерфейсов

  • функциональные интерфейсы — это интерфейсы, которые имеют только один абстрактный метод;
  • вы должны знать следующие встроенные функциональные интерфейсы: Предикат, Потребитель, Поставщик и Компаратор;

PREDICATE

public interface Predicate<T> {
   boolean test(T t);
}
Вход в полноэкранный режим Выход из полноэкранного режима
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();
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима
canguru
Войти в полноэкранный режим Выход из полноэкранного режима

ПОТРЕБИТЕЛЬ

public interface Consumer<T> {
    void accept(T t)
}
Войти в полноэкранный режим Выход из полноэкранного режима
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);
    }
}
Войти в полноэкранный режим Выход из полноэкранного режима
Hello World
Войти в полноэкранный режим Выход из полноэкранного режима

ПОСТАВЩИК

public interface Supplier<T> {  
     T get();  
}
Войти в полноэкранный режим Выход из полноэкранного режима
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();
    }
}
Войти в полноэкранный режим Выход из полноэкранного режима
42
Войти в полноэкранный режим Выход из полноэкранного режима

КОМПАРАТОР

  • правила, если возвращается:
    • отрицательное число означает, что первое значение меньше;
    • ноль означает, что они равны,
    • а положительное число означает, что первое значение больше.
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));
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима
[1, 2, 4, 5, 7]
Войти в полноэкранный режим Выход из полноэкранного режима

Работа с переменными в ламбдах

  • могут появляться:
    • список параметров;
    • локальные переменные, объявленные внутри тела лямбды;
    • переменные, на которые ссылаются из тела лямбды;
  • На параметры метода и локальные переменные разрешается ссылаться, если они являются фактически конечными (значение переменной не меняется после ее установки).

Вызов API с помощью лямбд

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));

    }
}
Вход в полноэкранный режим Выход из полноэкранного режима
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
Войти в полноэкранный режим Выход из полноэкранного режима

REMOVEIF()

  • принимает предикат, чтобы решить, что удалить из списка.

SORT()

  • Метод sort() принимает Comparator, который обеспечивает порядок сортировки.

FOREACH()

  • Принимает Consumer и вызывает эту лямбду для каждого встреченного элемента.

Оцените статью
Procodings.ru
Добавить комментарий