Как начать работать с Лямбда-выражениями в Java

в 7:01, , рубрики: java, java 8

Привет! Представляю вашему вниманию перевод статьи "How to start working with Lambda Expressions in Java" автора Luis Santiago.

До того как Лямбда-выражения были добавлены в JDK 8, я использовал их в таких языках как C# и С++. Когда они были добавлены в Java я стал изучать их подробнее.

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

Краткое введение

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

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

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

Функциональный интерфейс — это интерфейс, содержащий один и только один абстрактный метод.

Если вы посмотрите на определение стандартного интерфейса Runnable, то вы заметите как он попадает в определение функционального интерфейса, поскольку он определяет только один метод: run().

В приведенном ниже примере кода метод computeName является абстрактным и единственным методом в интерфейсе MyName, что делает его функциональным интерфейсом.

interface MyName{
  String computeName(String str);
}

Оператор Стрелка

Лямбда-выражения вводят новый оператор стрелка -> в Java. Он разделяет лямбда-выражение на 2 части:

(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 и определяют 2 выражения приветствия.

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


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")); 
}

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

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

interface MyGeneric {
	T compute(T t);
}

public static void main(String args[]){

	// String version of MyGenericInteface
	MyGeneric<String> reverse = (str) -> {
		String result = "";
		
		for(int i = str.length()-1; i >= 0; i--)
			result += str.charAt(i);
		
		return result;
	};

	// Integer version of MyGeneric
	MyGeneric<Integer> factorial = (Integer i) -> {
		int result = 1;
		int n = 5;
		
		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")); 
}

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

Автор: owin

Источник

Поделиться

* - обязательные к заполнению поля