Przystępujemy do następnego artykułu po zapowiedzianej dłuższej przerwie. Przyznajcie szczerze, niezbyt piękny był ten zapis z klasami, prawda? Tak trzeba było pisać zanim pojawiła się Java 8. OK, teraz przystąpimy do bardziej nowoczesnego sformułowania. Ono istnieje już od sześciu lat więc o nim też mogliście już nieraz usłyszeć. Przedstawiam Państwu "wyrażenie lambda" (ang. "lambda expression")!

WYRAŻENIE LAMBDA. WYJAŚNIENIA NA POCZĄTEK

Wyrażenie to określane jest również jako "funkcja anonimowa". Konstrukcja pozwala na wygodne osadzanie własnych metod, ale takich, które będą potrzebne tylko w tym jedynym przypadku. Nie piszemy typu zwracanej wartości, nie podajemy nazwy, nic z tych rzeczy! Zostało to tak sprytnie zbudowane, aby po prostu móc "wrzucić" instrukcje do wykonania na kształt "jednorazówki". Aby napisać, wykonać, wyrzucić. Co nie znaczy, że nie można podstawić czegoś takiego do zmiennej, aby korzystać do woli.

Wyrażenie lambda, oprócz "dziwnej" budowy funkcji, jest bardzo łatwo rozpoznawalne przez jeden nietypowy operator w postaci znaków myślnika i zamknięcia nawiasu trójkątnego postawionych obok siebie bez spacji (->). Taki sam operator znajdziecie w języku C podczas odwoływania się do zmiennych struktury czy unii poprzez wskaźnik. To nie jest artykuł o C więc zakończę ten temat. Ważne by sobie zakodować, że jak widzimy ten znaczek: ->, to mamy do czynienia z funkcją anonimową.

LAMBDA...COŚ MI TO MÓWI

Słowo "lambda" może kojarzyć się ekspertom od matematyki z "rachunkiem lambda" służącym do badania zagadnień dotyczących m.in. rekurencji i wyrażeń logicznych, ale na tym się kończy cała zbieżność. "Lambda" to również jedenasta litera greckiego alfabetu, a że język grecki zawsze "trzyma się" matmy, nikogo z nas to nie powinno dziwić.

WYRAŻENIE LAMBDA W PRAKTYCE

Wbrew temu, co można sobie pomyśleć o funkcji, która występuje tylko dla jednego przypadku, wyrażenie lambda czyni programowanie naprawdę o wiele prostszym. Przede wszystkim, dla wszelkiego rodzaju kolekcji, tablic, list, drzew, grafów, czy jeszcze innych konstrukcji złożonych z wielu mniejszych elementów. Powtórzę. O WIELE prostszym. Najczęściej spotykana postać to para nawiasów okrągłych (wśród nich mogą być parametry), powyższy operator i treść zawartych instrukcji. Tu jest ciekawie bo mamy dwa sposoby definicji:

  • jedna instrukcja

Możemy pominąć klamerki i tuż po tym operatorze podać jedną instrukcję, na przykład "System.out.println".

  • więcej instrukcji

Podajemy klamerki tworząc blok kodu do wykonania, a w nim wprowadzamy szereg instrukcji.

Wyrażenie lambda jest najczęściej stosowane do metod, które są w stanie obsłużyć całą kolekcję danych za pomocą jednej linijki kodu. Na przykład metoda "forEach" została zaprogramowana w sposób wspierający funkcję anonimową i potrafi naprawdę skrócić kod do granic wytrzymałości. Można też definiować własne funkcje tak, aby "był sens" podstawiania tych wyrażeń, aczkolwiek nie jest to często wykorzystywane więc tę część sobie pominiemy.

Grecka litera "lambda" - wyrażenie lambda

Wyrażenie lambda zawdzięcza swoją nazwę greckiej literze "lambda", która jest znana w matematyce między innymi w wykorzystaniu "rachunku lambda".

KOD WYKORZYSTUJĄCY FUNKCJĘ ANONIMOWĄ

Zniesiemy kolejny fragment? Oto przykład ukazujący kolekcję "ArrayList", zawarte w niej wartości zmiennoprzecinkowe, a także dla małej odmiany, konfrontację dwóch zapisów obsługi: za pomocą pętli rozszerzonej którą rozpatrywałem wcześniej oraz przy wykorzystaniu metody "forEach" i zawartego wyrażenia lambda. Spróbujcie zaobserwować różnice i wyciągnijcie samodzielnie wniosek:

  • KLASA "Main"
public class Main
{
	public static void main(String[] args)
	{
		new LambdaExpression();
	}
}
  • KLASA "LambdaExpression"
import Java. util. ArrayList;

public class LambdaExpression
{
	private ArrayList<Float> floats = new ArrayList<>();

	public LambdaExpression()
	{
		addFloats();
		printFloatsExtendedLoop();
		printFloatsForEach();
	}

	private void addFloats()
	{
		floats.add(13.13f);
		floats.add(56.789f);
		floats.add(0.56f);
		floats.add(657.2346f);
		floats.add(1.3f);
		floats.add(16.7395f);
		floats.add(131313.131313f);
	}

	private void printFloatsExtendedLoop()
	{
		for (Float f : floats)
		{
			System.out.println(f);
		}

		System.out.println();
	}

	private void printFloatsForEach()
	{
		floats.forEach((f) -> System.out.println(f));
		System.out.println();
	}
}

Ponownie musiałem "pomieszać" nazwę importu, aby Joomla pozwoliła mi normalnie zapisać artykuł. Pierwsza metoda dodaje liczby zmiennoprzecinkowe do listy, druga wypisuje je za pomocą znanej już pętli rozszerzonej "for each", a trzecia robi to samo, tylko za pomocą wyrażenia lambda w metodzie "forEach". Nie możecie stawiać znaku równości pomiędzy pętlą "for each", a metodą "forEach"!!! Zbieżność nazw taka sama, zasada działania też identyczna, ale konstrukcja jest już nieco inna. Pętla to pętla, a funkcja to funkcja i taki wniosek sobie zatrzymać w głowie.


To wszystko. Postawiłem większy nacisk na teorię niż sposoby zapisu bo tak naprawdę wyrażenie lambda w powyższym przypadku można zastąpić jeszcze prostszym zapisem, natomiast funkcja anonimowa sprawdza się doskonale w bardziej złożonych operacjach, w tym także prostym i mniej zabałaganionym dodawaniu zdarzeń do przycisków. Przypominam, że po to była prezentacja tego wyrażenia. Być może innym razem wrócę do tego i skupię się bardziej na samym "składaniu" bardziej skomplikowanych wyrażeń gdzie faktycznie będzie widać tę różnicę w linijkach kodu...