Что такое лямбда выражение в java
Перейти к содержимому

Что такое лямбда выражение в java

  • автор:

Лямбда-выражения

Среди новшеств, которые были привнесены в язык Java с выходом JDK 8, особняком стоят лямбда-выражения. Лямбда представляет набор инструкций, которые можно выделить в отдельную переменную и затем многократно вызвать в различных местах программы.

Основу лямбда-выражения составляет лямбда-оператор , который представляет стрелку -> . Этот оператор разделяет лямбда-выражение на две части: левая часть содержит список параметров выражения, а правая собственно представляет тело лямбда-выражения, где выполняются все действия.

Лямбда-выражение не выполняется само по себе, а образует реализацию метода, определенного в функциональном интерфейсе . При этом важно, что функциональный интерфейс должен содержать только один единственный метод без реализации.

public class LambdaApp < public static void main(String[] args) < Operationable operation; operation = (x,y)->x+y; int result = operation.calculate(10, 20); System.out.println(result); //30 > > interface Operationable

В роли функционального интерфейса выступает интерфейс Operationable , в котором определен один метод без реализации — метод calculate . Данный метод принимает два параметра — целых числа, и возвращает некоторое целое число.

По факту лямбда-выражения являются в некотором роде сокращенной формой внутренних анонимных классов, которые ранее применялись в Java. В частности, предыдущий пример мы можем переписать следующим образом:

public class LambdaApp < public static void main(String[] args) < Operationable op = new Operationable()< public int calculate(int x, int y)< return x + y; >>; int z = op.calculate(20, 10); System.out.println(z); // 30 > > interface Operationable

Чтобы объявить и использовать лямбда-выражение, основная программа разбивается на ряд этапов:

    Определение ссылки на функциональный интерфейс:

Operationable operation;
operation = (x,y)->x+y;
int result = operation.calculate(10, 20);

При этом для одного функционального интерфейса мы можем определить множество лямбда-выражений. Например:

Operationable operation1 = (int x, int y)-> x + y; Operationable operation2 = (int x, int y)-> x - y; Operationable operation3 = (int x, int y)-> x * y; System.out.println(operation1.calculate(20, 10)); //30 System.out.println(operation2.calculate(20, 10)); //10 System.out.println(operation3.calculate(20, 10)); //200

Отложенное выполнение

Одним из ключевых моментов в использовании лямбд является отложенное выполнение (deferred execution). То есть мы определяем в одном месте программы лямбда-выражение и затем можем его вызывать при необходимости неопределенное количество раз в различных частях программы. Отложенное выполнение может потребоваться, к примеру, в следующих случаях:

  • Выполнение кода отдельном потоке
  • Выполнение одного и того же кода несколько раз
  • Выполнение кода в результате какого-то события
  • Выполнение кода только в том случае, когда он действительно необходим и если он необходим

Передача параметров в лямбда-выражение

Параметры лямбда-выражения должны соответствовать по типу параметрам метода из функционального интерфейса. При написании самого лямбда-выражения тип параметров писать необязательно, хотя в принципе это можно сделать, например:

operation = (int x, int y)->x+y;

Если метод не принимает никаких параметров, то пишутся пустые скобки, например:

()-> 30 + 20;

Если метод принимает только один параметр, то скобки можно опустить:

n-> n * n;

Терминальные лямбда-выражения

Выше мы рассмотрели лямбда-выражения, которые возвращают определенное значение. Но также могут быть и терминальные лямбды, которые не возвращают никакого значения. Например:

interface Printable < void print(String s); >public class LambdaApp < public static void main(String[] args) < Printable printer = s->System.out.println(s); printer.print("Hello Java!"); > >

Лямбды и локальные переменные

Лямбда-выражение может использовать переменные, которые объявлены во вне в более общей области видимости — на уровне класса или метода, в котором лямбда-выражение определено. Однако в зависимости от того, как и где определены переменные, могут различаться способы их использования в лямбдах. Рассмотрим первый пример — использования переменных уровня класса:

public class LambdaApp < static int x = 10; static int y = 20; public static void main(String[] args) < Operation op = ()->< x=30; return x+y; >; System.out.println(op.calculate()); // 50 System.out.println(x); // 30 — значение x изменилось > > interface Operation

Переменные x и y объявлены на уровне класса, и в лямбда-выражении мы их можем получить и даже изменить. Так, в данном случае после выполнения выражения изменяется значение переменной x.

Теперь рассмотрим другой пример — локальные переменные на уровне метода:

public static void main(String[] args) < int n=70; int m=30; Operation op = ()->< //n=100; - так нельзя сделать return m+n; >; // n=100; - так тоже нельзя System.out.println(op.calculate()); // 100 >

Локальные переменные уровня метода мы также можем использовать в лямбдах, но изменять их значение нельзя. Если мы попробуем это сделать, то среда разработки (Netbeans) может нам высветить ошибку и то, что такую переменную надо пометить с помощью ключевого слова final , то есть сделать константой: final int n=70; . Однако это необязательно.

Более того, мы не сможем изменить значение переменной, которая используется в лямбда-выражении, вне этого выражения. То есть даже если такая переменная не объявлена как константа, по сути она является константой.

Блоки кода в лямбда-выражениях

Существуют два типа лямбда-выражений: однострочное выражение и блок кода. Примеры однострочных выражений демонстрировались выше. Блочные выражения обрамляются фигурными скобками. В блочных лямбда-выражениях можно использовать внутренние вложенные блоки, циклы, конструкции if, switch, создавать переменные и т.д. Если блочное лямбда-выражение должно возвращать значение, то явным образом применяется оператор return :

Operationable operation = (int x, int y)-> < if(y==0) return 0; else return x/y; >; System.out.println(operation.calculate(20, 10)); //2 System.out.println(operation.calculate(20, 0)); //0

Обобщенный функциональный интерфейс

Функциональный интерфейс может быть обобщенным, однако в лямбда-выражении использование обобщений не допускается. В этом случае нам надо типизировать объект интерфейса определенным типом, который потом будет применяться в лямбда-выражении. Например:

public class LambdaApp < public static void main(String[] args) < Operationableoperation1 = (x, y)-> x + y; Operationable operation2 = (x, y) -> x + y; System.out.println(operation1.calculate(20, 10)); //30 System.out.println(operation2.calculate(«20», «10»)); //2010 > > interface Operationable

Таким образом, при объявлении лямбда-выражения ему уже известно, какой тип параметры будут представлять и какой тип они будут возвращать.

Лямбда-выражения в Java — что это такое, зачем нужны и как выглядят

Лямбда-выражения или анонимные функции встречаются во многих языках программирования. Рассказываем про лямбда-выражения в Java с примерами.

Лямбда-выражения встречаются в разных языках программирования: JavaScript, PHP, C# и других. В этой статье поговорим о лямбда-выражениях в Java.

Для чего хорош Java?

Лямбда-выражения или анонимные функции — это блоки кода с параметрами, которые можно вызвать из другого места программы. Они называются анонимными, потому что в отличие от функций, у них нет имён. Слово «лямбда» пришло из лямбда-исчисления, которое придумал профессор Алонзо Чёрч. Он использовал греческую букву лямбда (λ), чтобы отметить параметры.

Лямбда-выражения в Java

  • Присутствуют начиная с 8 версии.
  • Являются анонимными классами, реализующими метод функционального интерфейса.
  • Имеют доступ только к final (или effectively final) переменным из охватывающей области видимости (для потокобезопасности).
  • Не могут возвращать значение в каких-то ветках, а в других не возвращать.
  • Позволяют уменьшить количество кода и повысить его читаемость.

Примеры синтаксиса лямбда-выражений в Java

Лямбда-выражения в Java состоят из параметров и стрелки —> отделяющей тело функции. Скобки нужны, если параметров 0 или больше одного. Для однострочных лямбд ключевое слово return не обязательно.

(список параметров) -> тело лямбды

Без параметров

@FunctionalInterface interface MyFunctionalInterface < //метод без параметров public String sayHello(); >public class Example < public static void main(String args[]) < // лямбда выражение MyFunctionalInterface msg = () ->< return "Привет мир"; >; System.out.println(msg.sayHello()); > > 

Этот код выведет в консоль текст: «Привет мир!».

C параметром

import java.awt.*; public class ButtonListenerNewWay < public static void main(String[] args) < Frame frame=new Frame("ActionListener java8"); Button b=new Button("Click Here"); b.setBounds(50,100,80,50); b.addActionListener(e ->System.out.println("Привет мир!")); frame.add(b); frame.setSize(200,200); frame.setLayout(null); frame.setVisible(true); > > 

В этом примере лямбда-выражение используется для обработки нажатия кнопки.

С несколькими параметрами

interface StringConcat < public String sconcat(String a, String b); >public class Example < public static void main(String args[]) < StringConcat s = (str1, str2) ->str1 + str2; System.out.println("Result: "+s.sconcat("Hello ", "World")); > > 

Здесь лямбда-выражение склеивает строки.

Приёмы и хитрости начинающего Java-программиста

Следите за новыми постами по любимым темам

Подпишитесь на интересующие вас теги, чтобы следить за новыми постами и быть в курсе событий.

Подписаться на тег

Для начинающих

Подписаться на тег

Что думаете?
1 комментарий
Сначала интересные

Аватар пользователя Stanislav Paliutin

08 нояб 2021 08 нояб 2021 в 17:11

«Лямбда-выражения в Java. Являются анонимными классами. » Не могли бы Вы привести пруфы данному утверждению. В JLS я не нашёл конкретных определений. Но знаю несколько принципиальных различий, которые проводят границу между этими сущностями: 1. способ компиляции. Компилятор Java компилирует лямбда-выражения и преобразует их в закрытый метод класса. Этот метод использует инструкцию `invokedynamic`. А вот анонимный класс компилируется в отдельный файл с байт-кодом. 2. анонимный класс создает новый скоуп, лямбда работает в текущем. Это значит, что объявление переменной с именем, которое уже используется снаружи, в лямбде вызовет ошибку компиляции «variable is already defined», в анонимном классе скроет (shadowing) внешнюю переменную. 3. то же и с использованием ключевого слова `this`. В анонимных классах ключевое слово `this` ссылается на сам анонимный класс, тогда как для лямбда-выражения ключевое слово `this` ссылается на класс, в котором написано лямбда-выражение.

Лямбды — Java: Коллекции

Лямбда-функции — это анонимные функции, которые можно сохранять и передавать как обычные переменные.

Введение

Общий вид лямбды (параметры) -> выражение или (параметры) -> . Стрелка — это лямбда-оператор.

Чаще всего используются три функциональных интерфейса:

  • Predicate — принимает параметр и возвращает логическое значение
  • Consumer — который принимает параметр и не возвращает никакого значения
  • Function — принимает параметр и возвращает какое-то значение
// Допустим, нам нужно вывести на экран // список домашних животных и вернуть только имена питомцев, // отсортированные по алфавиту ListMapString, String>> animals = List.of( Map.of("name", "Spooky", "animal", "dog"), Map.of("name", "Tom", "animal", "cat"), Map.of("name", "Jimmy", "animal", "bird"), Map.of("name", "Buddy", "animal", "dog"), Map.of("name", "Elsa", "animal", "dog"), Map.of("name", "Murka", "animal", "cat") ); 
// Создадим метод getPetNames() в классе AppExample // Для этого будем использовать Stream API и лямбды class AppExample  public static ListString> getPetNames(ListMapString, String>> animals, String animal)  return animals.stream() // Сначала отфильтруем всех питомцев, например только собак // Метод filter принимает в качестве параметра Predicate // Лямбда принимает вид питомца и возвращает true, если оно совпадает с требуемым .filter(pet -> pet.get("animal").equals(animal)) // Затем сделаем отображение, оставим только имя питомца // Метод map принимает на вход Function // Она принимает текущий элемент стрима и возвращает новый измененный .map(pet -> pet.get("name")) // Сортируем имена // Метод sorted принимает на вход Function // Лямбда принимает два соседних элемента стрима и возвращает 1, 0 или -1 // в зависимости от того, больше ли первый элемент чем второй, равен или меньше .sorted((name1, name2) -> name1.compareTo(name2)) .collect(Collectors.toList()); > > 

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Что такое лямбда выражение в java

Denis Gritsay Уровень 20

28 октября 2023

это : // Старый способ: List list = Arrays.asList(1,2,3,4,5,6,7); int sum = 0; for(Integer n : list) < int x = n * n; sum = sum + x; >System.out.println(sum); намного понятнее и легче в восприятию чем это List list = Arrays.asList(1,2,3,4,5,6,7); int sum = list.stream().map(x -> x*x).reduce((x,y) -> x + y).get(); System.out.println(sum); Так что лямбду нужно я думаю использовать не там где пара лишних строк кода, ведь сейчас не 17 век когда проблема с бумагой, а там где это реально полезно и нужно

Vitaly Demchenko Уровень 30

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *