Содержание
Лямбды и функциональные интерфейсы
Написание простых ламбдас
- Функциональное программирование — это способ писать код более декларативно. Вы указываете, что вы хотите сделать, а не работаете с состоянием объектов. Вы больше внимания уделяете выражениям, чем циклам.
- В функциональном программировании для написания кода используются лямбда-выражения.
- Лямбда-выражение — это неименованный метод.
ПРИМЕР ЛЯМБДА-ВЫРАЖЕНИЯ
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 и вызывает эту лямбду для каждого встреченного элемента.