Введення в лямбда-вирази. Вбудовані функціональні інтерфейси
Введення в лямбда-вирази. Вбудовані функціональні інтерфейси
Введення в лямбда-вирази
Лямбда-вирази — це новий синтаксичний елемент, доданий у Java 8, який дозволяє писати коротші та більш читабельні функціональні вирази, особливо в контексті функціонального програмування. Лямбда-вирази використовуються для передачі функцій як параметрів методів або для створення анонімних функцій.
Основний синтаксис лямбда-виразів
(параметри) -> {тіло виразу}
- Параметри: перелік параметрів, який передається лямбда-виразу (може бути порожнім).
- Оператор `->`: розділяє список параметрів та тіло виразу.
- Тіло виразу: це код, який виконується при виклику лямбда-виразу.
Приклади:
1. Лямбда без параметрів:
() -> System.out.println(“Hello, World!”);
2. Лямбда з одним параметром:
x -> x * x
3. Лямбда з кількома параметрами:
(x, y) -> x + y
4. Лямбда з блоком коду:
Якщо лямбда-вираз містить кілька операторів, необхідно використовувати фігурні дужки `{}`.
(x, y) -> {
int result = x + y;
return result;
}
Лямбда-вирази та функціональні інтерфейси
Лямбда-вирази можуть використовуватися лише з функціональними інтерфейсами. Це інтерфейси, які містять тільки один абстрактний метод. Їх часто називають SAM (Single Abstract Method) інтерфейсами. Лямбда-вираз дозволяє реалізувати цей єдиний метод у скороченій формі.
Приклад функціонального інтерфейсу:
@FunctionalInterface
interface Calculator {
int calculate(int x, int y);
}
Використання лямбда-виразу для реалізації цього інтерфейсу:
Calculator add = (x, y) -> x + y;
Calculator multiply = (x, y) -> x * y;
int sum = add.calculate(5, 3); // 8
int product = multiply.calculate(5, 3); // 15
Вбудовані функціональні інтерфейси
Java 8 вводить кілька стандартних функціональних інтерфейсів, які можна використовувати з лямбда-виразами. Всі вони знаходяться в пакеті `java.util.function`.
1. Function<T, R>
Цей інтерфейс приймає один параметр типу `T` і повертає результат типу `R`. Метод: `R apply(T t)`.
Приклад:
Function<Integer, String> intToString = (i) -> “Number: ” + i;
System.out.println(intToString.apply(5)); // Output: “Number: 5”
2. Consumer<T>
Приймає один аргумент типу `T` і не повертає результату. Використовується для виконання операцій над переданим параметром. Метод: `void accept(T t)`.
Приклад:
Consumer<String> print = (str) -> System.out.println(str);
print.accept(“Hello, Java!”); // Output: “Hello, Java!”
3. Supplier<T>
Не приймає жодних параметрів, але повертає значення типу `T`. Метод: `T get()`.
Приклад:
Supplier<Double> randomValue = () -> Math.random();
System.out.println(randomValue.get()); // Output: випадкове число
4. Predicate<T>
Приймає один параметр типу `T` і повертає логічне значення (boolean). Метод: `boolean test(T t)`.
Приклад:
Predicate<Integer> isEven = (n) -> n % 2 == 0;
System.out.println(isEven.test(4)); // Output: true
System.out.println(isEven.test(5)); // Output: false
5. BiFunction<T, U, R>
Приймає два параметри типу `T` і `U` та повертає результат типу `R`. Метод: `R apply(T t, U u)`.
Приклад:
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
System.out.println(add.apply(5, 3)); // Output: 8
6. UnaryOperator<T>
Це спеціальний випадок `Function`, який приймає один аргумент і повертає результат того ж типу. Метод: `T apply(T t)`.
Приклад:
UnaryOperator<Integer> square = (x) -> x * x;
System.out.println(square.apply(4)); // Output: 16
7. BinaryOperator<T>
Це спеціальний випадок `BiFunction`, який приймає два аргументи одного типу і повертає результат того ж типу. Метод: `T apply(T t1, T t2)`.
Приклад:
BinaryOperator<Integer> multiply = (a, b) -> a * b;
System.out.println(multiply.apply(5, 3)); // Output: 15
Приклад використання лямбда-виразів і функціональних інтерфейсів
import java.util.function.*;
public class LambdaExample {
public static void main(String[] args) {
// Function: приймає Integer, повертає String
Function<Integer, String> intToString = (i) -> “Number: ” + i;
System.out.println(intToString.apply(10));
// Consumer: приймає String, нічого не повертає
Consumer<String> print = (s) -> System.out.println(s);
print.accept(“Hello, Consumer!”);
// Supplier: не приймає параметрів, повертає Double
Supplier<Double> randomValue = () -> Math.random();
System.out.println(randomValue.get());
// Predicate: приймає Integer, повертає boolean
Predicate<Integer> isEven = (n) -> n % 2 == 0;
System.out.println(isEven.test(8));
// BiFunction: приймає два Integer, повертає Integer
BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
System.out.println(sum.apply(5, 7));
}
}
Висновок
- Лямбда-вирази роблять код коротшим і більш читабельним, особливо коли потрібно передати функцію як параметр.
- Лямбда-вирази працюють лише з функціональними інтерфейсами, які мають один абстрактний метод.
- Java 8 додає багато вбудованих функціональних інтерфейсів у пакеті `java.util.function`, таких як `Function`, `Predicate`, `Consumer`, `Supplier`, які дозволяють ефективно використовувати лямбда-вирази у різних контекстах.