Что такое Lambda
Лямбда-выражение в Java — это компактная форма записи анонимного метода, который можно передавать в качестве значения, сохранять в переменную и вызывать в любом месте программы. Оно реализует единственный абстрактный метод функционального интерфейса, обеспечивая лаконичный способ описания поведения без создания отдельного класса.
Как это работает
Лямбда-выражение состоит из списка параметров, оператора -> и тела. Список параметров соответствует параметрам абстрактного метода функционального интерфейса, а тело — его реализации. Типы параметров можно опускать, если они однозначно выводятся из контекста. Если параметр один, скобки можно не ставить; если параметров нет, используются пустые скобки (). Тело может быть выражением (значение которого возвращается) или блоком с фигурными скобками, где для возврата значения используется return.
Пример простейшей лямбды:
interface Operationable {
int calculate(int x, int y);
}
Operationable operation = (x, y) -> x + y;
int result = operation.calculate(10, 20); // 30Здесь лямбда (x, y) -> x + y реализует метод calculate, складывая два числа. Типы x и y выводятся из сигнатуры интерфейса.
Разновидности лямбда-выражений
- Выраженческие (expression lambdas) — тело состоит из одного выражения, которое автоматически возвращается. Например,
(x, y) -> x + y. - Блочные (block lambdas) — тело заключено в фигурные скобки, допускает несколько операторов, циклы, условные конструкции. Требуется явный
return, если метод должен вернуть значение.
Operationable safeDivide = (x, y) -> {
if (y == 0) {
return 0;
} else {
return x / y;
}
};- Без возвращаемого значения — если метод функционального интерфейса возвращает
void, лямбда может содержать только вызовы или выражения с побочными эффектами.
interface Printable {
void print(String s);
}
Printable printer = s -> System.out.println(s);
printer.print("Hello, world");Передача лямбды в метод
Лямбды часто передают как аргументы методов, ожидающих функциональный интерфейс. Это позволяет параметризовать поведение: метод выполняет общую логику, а конкретное действие задаётся лямбдой.
interface Condition {
boolean isAppropriate(int n);
}
private static int sum(int[] numbers, Condition condition) {
int result = 0;
for (int i : numbers) {
if (condition.isAppropriate(i)) {
result += i;
}
}
return result;
}
public static void main(String[] args) {
int[] numbers = {0, 1, 0, 3, 0, 5, 0, 7, 0, 9};
System.out.println(sum(numbers, (n) -> n != 0)); // 25
}Здесь лямбда (n) -> n != 0 задаёт условие отбора элементов для суммирования.
Подводные камни и ограничения
- Функциональный интерфейс обязателен — лямбда может быть использована только там, где ожидается тип, являющийся функциональным интерфейсом (интерфейс с одним абстрактным методом). Если абстрактных методов несколько, лямбда не подойдёт.
- Захват переменных — лямбда может обращаться к локальным переменным, но они должны быть эффективно финальными (не изменяться после инициализации). Изменение такой переменной внутри лямбды запрещено.
- Отложенное выполнение — лямбда определяет поведение, но не выполняет его сразу. Вызов происходит только при вызове метода функционального интерфейса, что удобно для передачи логики как параметра.
- Сравнение с анонимными классами — лямбды компактнее, но не могут иметь полей и методов, как анонимные классы. Для простых реализаций лямбды предпочтительнее.
Коротко
- Лямбда — это реализация единственного абстрактного метода функционального интерфейса, записанная в виде
(параметры) -> тело. - Тело может быть выражением или блоком с
return; типы параметров часто опускаются. - Лямбды удобно передавать в методы для параметризации поведения, например, в
sumс условием. - Помните про ограничения: функциональный интерфейс обязателен, захватываемые переменные должны быть эффективно финальными.