Лямбда-выражения Java
Лямбда-выражения, также известные как замыкания, — важнейшая новая возможность, благодаря которой вышел Java 8.
Лямбда позволяет передать функцию в метод в качестве параметра (функции передаются в методы как аргументы).
Использование лямбда-выражений позволяет сделать код более кратким и компактным.
Синтаксис
Синтаксис лямбда-выражения выглядит следующим образом:
parameters— это список параметров,expressionили{ statements; }— это тело лямбда-выражения. Если есть только один параметр, круглые скобки можно опустить; если параметров нет, пустые круглые скобки всё равно обязательны.
Ниже приведён простой пример, показывающий использование лямбда-выражения для вычисления суммы двух чисел:
Пример
MathOperation addition = (a, b) -> a + b;
// Вызов лямбда-выражения
int result = addition.operation(5, 3);
System.out.println("5 + 3 = " + result);
В приведённом выше примере MathOperation — это функциональный интерфейс, содержащий абстрактный метод operation. Лямбда-выражение(a, b) -> a + bреализует этот абстрактный метод, представляя операцию сложения двух параметров.
Лямбда-выражения можно использовать в различных сценариях, включая операции с коллекциями, обработку событий и т. д. Ниже приведён пример использования лямбда-выражения для перебора списка:
Пример
// Использование лямбда-выражения для перебора списка
names.forEach(name -> System.out.println(name));
Лямбда-выражения привносят в Java более функциональный стиль программирования, делая код более кратким и читаемым. Они являются важным улучшением функционального программирования в Java 8.
Важные особенности
Лаконичность
Лямбда-выражения обеспечивают более краткий синтаксис, особенно подходящий для функциональных интерфейсов. По сравнению с традиционными анонимными внутренними классами лямбда-выражения делают код более компактным и уменьшают количество шаблонного кода.
Пример
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello World!");
}
};
// Использование лямбда-выражения
Runnable runnable2 = () -> System.out.println("Hello World!");
Поддержка функционального программирования
Лямбда-выражения являются проявлением функционального программирования. Они позволяют передавать функции в качестве аргументов методам или возвращать их как возвращаемые значения. Эта поддержка делает Java более гибкой в функциональном программировании, позволяя лучше справляться с такими задачами, как операции над коллекциями и параллельные вычисления.
Пример
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));
Захват переменных
Лямбда-выражения могут обращаться к переменным во внешней области видимости. Эта возможность называется захватом переменных. Лямбда-выражения могут неявно захватывать локальные переменные, которые являются final или эффективно final.
Пример
int x = 10;
MyFunction myFunction = y -> System.out.println(x + y);
myFunction.doSomething(5); // Вывод 15
Ссылки на методы
Лямбда-выражения можно дополнительно упростить с помощью ссылок на методы. Ссылки на методы позволяют напрямую ссылаться на методы существующих классов или объектов без написания избыточного кода.
Пример
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(System.out::println);
Параллелизм
Лямбда-выражения делают реализацию параллельных операций более удобной. Используя Stream API в сочетании с лямбда-выражениями, можно легче реализовать параллельные вычисления, что повышает производительность программы.
Пример
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream().mapToInt(Integer::intValue).sum();
Введение лямбда-выражений делает программирование на Java более гибким и лаконичным и способствует развитию функционального программирования.
Примеры лямбда-выражений
Простые примеры лямбда-выражений:
// 1. 不需要参数,返回值为 5 () -> 5 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x // 3. 接受2个参数(数字),并返回他们的差值 (x, y) -> x – y // 4. 接收2个int型整数,返回他们的和 (int x, int y) -> x + y // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) (String s) -> System.out.print(s)
Введите следующий код в файл Java8Tester.java:
Файл Java8Tester.java
Выполните приведенный выше скрипт, и вывод будет:
$ javac Java8Tester.java $ java Java8Tester 10 + 5 = 15 10 - 5 = 5 10 x 5 = 50 10 / 5 = 2 Hello Example Hello Google
При использовании лямбда-выражений следует учитывать следующие два момента:
-
Лямбда-выражения в основном используются для определения интерфейсов методного типа для встроенного выполнения (например, простой интерфейс метода). В приведенном выше примере мы использовали различные типы лямбда-выражений для определения методов интерфейса MathOperation, а затем определили выполнение operation.
-
Лямбда-выражения избавляют от хлопот с использованием анонимных методов и дают Java простые, но мощные возможности функционального программирования.
Область видимости переменных
Лямбда-выражения могут ссылаться только на внешние локальные переменные, помеченные как final. То есть локальные переменные, определённые вне области видимости лямбда-выражения, не могут быть изменены внутри лямбда-выражения; в противном случае возникнет ошибка компиляции.
Введите следующий код в файл Java8Tester.java:
Файл Java8Tester.java
Выполните приведенный выше скрипт, и вывод будет:
$ javac Java8Tester.java $ java Java8Tester Hello! Example
Мы также можем напрямую обращаться к внешним локальным переменным в лямбда-выражении:
Файл Java8Tester.java
Локальные переменные в лямбда-выражениях не нужно объявлять как final, но они не должны изменяться последующим кодом (то есть они неявно имеют семантику final).
int num = 1; Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num)); s.convert(2); num = 5; //报错信息:Local variable num defined in an enclosing scope must be final or effectively final
Не разрешается объявлять параметр или локальную переменную с тем же именем, что и локальная переменная внутри лямбда-выражения.
String first = ""; Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); //编译会出错
Другие расширения
Новые возможности Java 8