Як розпочати роботу з лямбда-виразами на Java

До того, як підтримку виразів Лямбда додав JDK 8, я використовував лише їх приклади на таких мовах, як C # та C ++.

Коли цю функцію було додано до Java, я почав розглядати їх трохи ближче.

Додавання лямбда-виразів додає елементи синтаксису, що збільшують виражальну силу Java. У цій статті я хочу зосередитись на основних концепціях, з якими вам потрібно ознайомитись, щоб сьогодні ви могли почати додавати лямбда-вирази до свого коду.

Швидкий вступ

Лямбда-вирази використовують переваги можливостей паралельних процесів багатоядерних середовищ, як це видно за підтримки конвеєрних операцій з даними в потоковому API.

Це анонімні методи (методи без імен), що використовуються для реалізації методу, визначеного функціональним інтерфейсом. Важливо знати, що таке функціональний інтерфейс, перш ніж забруднювати руки лямбда-виразами.

Функціональний інтерфейс

Функціональний інтерфейс - це інтерфейс, який містить один і лише один абстрактний метод.

Якщо ви подивіться на визначення інтерфейсу Java стандарт Runnable, ви помітите , як він потрапляє в визначення функціонального інтерфейсу , оскільки він визначає тільки один метод: run().

У наведеному нижче прикладі коду метод computeNameє неявно абстрактним і є єдиним методом, визначеним, що робить MyName функціональним інтерфейсом.

interface MyName{ String computeName(String str); }

Оператор стрілки

Лямбда-вирази вводять новий оператор стрілки ->в Java. Він ділить лямбда-вирази на дві частини:

(n) -> n*n

Ліва сторона вказує параметри, необхідні для виразу, які також можуть бути порожніми, якщо параметри не потрібні.

Права сторона - це лямбда-тіло, яке визначає дії лямбда-виразу. Можливо, було б корисно думати про цей оператор як “стає”. Наприклад, "n стає n * n", або "n стає n квадратом".

Маючи на увазі концепції функціонального інтерфейсу та оператора стрілки, ви можете скласти простий лямбда-вираз:

interface NumericTest { boolean computeTest(int n); } public static void main(String args[]) { NumericTest isEven = (n) -> (n % 2) == 0; NumericTest isNegative = (n) -> (n < 0); // Output: false System.out.println(isEven.computeTest(5)); // Output: true System.out.println(isNegative.computeTest(-5)); }
interface MyGreeting { String processName(String str); } public static void main(String args[]) { MyGreeting morningGreeting = (str) -> "Good Morning " + str + "!"; MyGreeting eveningGreeting = (str) -> "Good Evening " + str + "!"; // Output: Good Morning Luis! System.out.println(morningGreeting.processName("Luis")); // Output: Good Evening Jessica! System.out.println(eveningGreeting.processName("Jessica")); }

Змінні morningGreetingта eveningGreetingрядки 6 та 7 у зразку вище посилаються на MyGreetingінтерфейс та визначають різні вирази привітання.

Під час написання лямбда-виразу також можна явно вказати тип параметра у виразі так:

MyGreeting morningGreeting = (String str) -> "Good Morning " + str + "!"; MyGreeting eveningGreeting = (String str) -> "Good Evening " + str + "!";

Блокувати лямбда-вирази

Наразі я охопив зразки лямбд з одним виразом. Існує інший тип виразу, який використовується, коли код праворуч від оператора стрілки містить більше одного виразу, відомого як блок лямбди :

interface MyString { String myStringFunction(String str); } public static void main (String args[]) { // Block lambda to reverse string MyString reverseStr = (str) -> { String result = ""; for(int i = str.length()-1; i >= 0; i--) result += str.charAt(i); return result; }; // Output: omeD adbmaL System.out.println(reverseStr.myStringFunction("Lambda Demo")); }

Загальні функціональні інтерфейси

Лямбда-вираз не може бути загальним. Але функціональний інтерфейс, пов'язаний з лямбда-виразом, може. Можна написати один загальний інтерфейс і обробляти різні типи повернення, як це:

interface MyGeneric { T compute(T t); } public static void main(String args[]){ // String version of MyGenericInteface MyGeneric reverse = (str) -> { String result = ""; for(int i = str.length()-1; i >= 0; i--) result += str.charAt(i); return result; }; // Integer version of MyGeneric MyGeneric factorial = (Integer n) -> { int result = 1; for(int i=1; i <= n; i++) result = i * result; return result; }; // Output: omeD adbmaL System.out.println(reverse.compute("Lambda Demo")); // Output: 120 System.out.println(factorial.compute(5)); }

Лямбда-вирази як аргументи

Одним із поширених видів використання лямбд є передача їх як аргументів.

Вони можуть бути використані в будь-якому фрагменті коду, який забезпечує цільовий тип. Я вважаю це захоплюючим, оскільки це дозволяє мені передавати виконуваний код як аргументи методам.

Щоб передавати лямбда-вирази як параметри, просто переконайтесь, що функціональний тип інтерфейсу сумісний з необхідним параметром.

interface MyString { String myStringFunction(String str); } public static String reverseStr(MyString reverse, String str){ return reverse.myStringFunction(str); } public static void main (String args[]) { // Block lambda to reverse string MyString reverse = (str) -> { String result = ""; for(int i = str.length()-1; i >= 0; i--) result += str.charAt(i); return result; }; // Output: omeD adbmaL System.out.println(reverseStr(reverse, "Lambda Demo")); }

Ці концепції дадуть вам добру основу для початку роботи з лямбда-виразами. Погляньте на свій код і подивіться, де ви можете збільшити виразну силу Java.