Что такое Lambda-выражения в Java?
В Java lambda-выражения (или лямбда-выражения) — это способ записи анонимной функции, которую можно передать как параметр или использовать как объект функционального интерфейса.
Они были добавлены в Java 8 (2014 год) и значительно упростили функциональный стиль программирования.
🧠 Что такое lambda-выражение?
Это краткая форма записи однометодного объекта интерфейса (функционального интерфейса). Позволяет писать меньше кода при использовании вместо анонимных классов.
📌 Синтаксис lambda-выражения:
(параметры) -> { тело }
🔍 Примеры:
▶ Пример 1: без параметров
() -> System.out.println("Привет из лямбды!");
▶ Пример 2: с одним параметром
x -> x \* x
▶ Пример 3: с несколькими параметрами и телом
(a, b) -> {
int result = a + b;
return result;
}
✅ Lambda = объект функционального интерфейса
Чтобы использовать lambda-выражение, нужно функциональный интерфейс — интерфейс с одним абстрактным методом.
▶ Пример интерфейса:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
▶ Использование:
MathOperation add = (a, b) -> a + b;
System.out.println(add.operation(5, 3)); // 8
🔷 Преимущества lambda-выражений:
Преимущество | Описание |
---|---|
✅ Краткость | Меньше кода по сравнению с анонимными классами |
--- | --- |
✅ Читаемость | Более декларативный стиль |
--- | --- |
✅ Функциональность | Позволяют использовать функциональный стиль |
--- | --- |
✅ Удобство в коллекциях | Используются в Streams, Collections.sort(), forEach() |
--- | --- |
💡 Сравнение: до и после Java 8
🔴 До Java 8 (анонимный класс):
Runnable r = new Runnable() {
public void run() {
System.out.println("Hello");
}
};
✅ После Java 8 (лямбда):
Runnable r = () -> System.out.println("Hello");
🔧 Где применяются lambda-выражения
- **Streams API
** - **Коллекции (sort(), removeIf() и т.д.)
** - **Functional Interfaces (Predicate, Function, Consumer и т.п.)
** - **Обработка событий (например, в GUI)
**
📚 Стандартные функциональные интерфейсы (из java.util.function):
Интерфейс | Назначение | Пример |
---|---|---|
Predicate<T> | принимает T, возвращает boolean | x -> x > 0 |
--- | --- | --- |
Function<T,R> | принимает T, возвращает R | x -> x.toString() |
--- | --- | --- |
Consumer<T> | принимает T, ничего не возвращает | x -> System.out.println(x) |
--- | --- | --- |
Supplier<T> | ничего не принимает, возвращает T | () -> "Java" |
--- | --- | --- |
BinaryOperator<T> | принимает два T, возвращает T | (a, b) -> a + b |
--- | --- | --- |
🧩 Пример: сортировка списка
List<String> names = Arrays.asList("Аня", "Борис", "Вика");
names.sort((s1, s2) -> s1.compareTo(s2));
names.forEach(name -> System.out.println(name));
🛑 Ограничения и особенности
-
Лямбда-выражения нельзя перегружать — типы должны быть однозначны.
-
Использовать можно только функциональные интерфейсы.
-
В теле лямбды можно использовать только effectively final переменные (неизменяемые).
🧠 Что значит effectively final?
Это переменная, которая не изменяется после присваивания, даже если не помечена как final.
String greeting = "Привет"; // effectively final
Runnable r = () -> System.out.println(greeting); // OK
📌 Разница между ==, equals() и lambda:
-
Lambda — это объект, но он не имеет уникального класса.
-
Лямбды не равны между собой по ==, даже если выглядят одинаково.
-
Нельзя переопределять equals() для сравнения лямбд.
✅ Вывод
Lambda-выражения в Java:
-
Позволяют создавать анонимные функции.
-
Используются вместе с функциональными интерфейсами.
-
Улучшают читаемость и краткость кода.
-
Широко применяются в Stream API и обработке коллекций.
-
Не заменяют полностью классы, но упрощают синтаксис.