Лямбда выражения
Лямбда выражения
Лямбда — это функция, которая принимает один аргумент и возвращает значение. Она используется для создания анонимных функций в языке программирования Java. Лямбда выражения позволяют создавать функции без создания отдельного класса или метода. Они используются для обработки коллекций данных, отправки событий в обработчики и других задач.
Лямбда - это функция, описывающая обработку данных, и оно очень похоже на метод. Однако его можно передавать как аргумент. Существует множество классов, методы которых ожидают именно лямбда-выражения в качестве аргументов. Наиболее распространенные из них реализованы в интерфейсе Stream API
public interface PlainInterface {String action(int x, int y);}
public class Main {public static void main(String[] args) {PlainInterface plainInterface = new PlainInterface() {@Overridepublic String action(int x, int y) {return String.valueOf(x + y);}};System.out.println(plainInterface.action(2, 5));}}
Но давайте сначала перепишем реализацию с использованием лямбда выражения.
public class Main {public static void main(String[] args) {PlainInterface plainInterface = (x, y) -> String.valueOf(x - y);System.out.println(plainInterface.action(5, 3));}
Изменился синтаксис, и код стал проще. Не нужно создавать экземпляр класса, не нужна аннотация оверрайд и, если посмотреть внимательней, мы не передаем типы параметров и не указываем ключевое слово return. Всё это делает компилятор! Ну и если говорить о мелочах, не нужно оборачивать реализацию в фигурные скобки и завершать её точкой с запятой. Однако фигурные скобки, ограничивающие блок кода, не нужны только если реализация умещается в одну строку. Если же вы захотите многострочную реализацию, то и фигурные скобки и return вернутся на свои места. Это чуть больше похоже на классическую реализацию, однако всё же короче и лаконичней! И ещё обращу ваше внимание на новую аннотацию @FunctionalInterface. Она проверяет, является ли интерфейс функциональным, то есть описывает всего один метод. Это обязательно для лямбда выражений и если это не так, аннотация просто не даст коду собраться.
@FunctionalInterfacepublic interface PlainInterface {String action(int x, int y);}
public static void main(String[] args) {PlainInterface plainInterface = (x, y) -> {String str = String.valueOf(x + y);return str + "!";};System.out.println(plainInterface.action(5, 5));}
А давайте попробуем создать несколько реализаций!
static PlainInterface plainInterface;public static void main(String[] args) {plainInterface = (x, y) -> String.valueOf(x + y);print(5, 5);plainInterface = (x, y) -> String.valueOf(x - y);print(5, 5);plainInterface = (x, y) -> String.valueOf(x * y);print(5, 5);}private static void print(int x, int y) {System.out.println(plainInterface.action(x, y));}
Для демонстрации я создал метод print, который выводит в консоль результаты работы нашего лямбда-выражения. В методе print я трижды переопределил поведение лямбда-выражения и трижды вызвал метод print с одинаковыми аргументами. Результаты соответствуют ожидаемому поведению: сумма, разность или произведение. Это простой и наглядный пример переопределения метода plainInterface непосредственно в коде! Давайте теперь изменим код еще немного.
public class Main {static PlainInterface plainInterface;static PlainInterface anInterface;static PlainInterface2 anInterface2;public static void main(String[] args) {anInterface = (x, y) -> String.valueOf(x+y);System.out.println(anInterface.action(5,5));anInterface2 = Integer::compare;System.out.println(anInterface2.action(5,15));}}@FunctionalInterfaceinterface PlainInterface{ String action(int x, int y);}@FunctionalInterfaceinterface PlainInterface2{ int action(int x, int y);}
Я добавил еще один интерфейс с другой сигнатурой метода и реализовал его по-другому. В этой реализации нет переменных, только имя класса и имя метода, разделенные двумя двоеточиями. Как это работает? Метод compare класса Integer принимает два int параметра и возвращает int значение. Если бы мы описали это с помощью обычного лямбда-выражения, то получили бы следующий код.
PlainInterface2 interface2 = (x, y) -> Integer.compare(x, y);
Мы создали своего рода оболочку для метода compare, и лямбда снова предлагает нам лаконичное решение. Всё, что нам нужно сделать в реализации — это указать имя класса, а через двоеточие — имя метода. Компилятор сам поймёт, что методу нужны два параметра, а мы передаем ему именно два параметра нужных типов, и метод возвращает то, что требует наш функциональный интерфейс. Вот откуда у нас такой простой синтаксис.
Лямбда создаются на основе функциональных интерфейсов и позволяют переопределить поведение непосредственно в коде, упрощая синтаксис. Они значительно облегчают написание кода, делают его короче и понятнее, напоминая нам о синтаксическом сахаре.
Лямбда позволяют использовать преимущества функционального программирования на полностью объектно-ориентированном языке Java.
● Лямбды формируются на основе функционального интерфейса и могут переопределять поведение прямо в коде с упрощенным синтаксисом.
● Лямбды сильно упрощают программирование, делают код проще и короче! И этим напоминают синтаксический сахар.
● Лямбды, являясь функциями, позволяют использовать в полностью объектно-ориентированном языке программирования Java плюсы из функционального программирования. В частности передавать и хранить сами реализации методов!