Se afișează postările cu eticheta lambda. Afișați toate postările
Se afișează postările cu eticheta lambda. Afișați toate postările

joi, 26 februarie 2026

Expresiile lambda

O expresie lambda este un bloc scurt de cod care primește parametri și returnează o valoare. Mai este numită funcție anonimă (fără nume) și permite scrierea unui cod mai scurt și mai clar, în special atunci când lucrăm cu colecții sau interfețe funcționale.

O interfață funcțională în Java este o interfață care conține exact o singură metodă abstractă (SAM - Single Abstract Method), servind ca bază pentru expresiile lambda și transmiterea acțiunilor ca parametru.

Sintaxa expresiilor lambda:
(parametri) -> expresie
sau
(parametri) -> { instructiuni }
Exemple:
(x) -> x * 2
(x, y) -> x + y
() -> System.out.println("Salut!")


După cum se observă în sintaxa expresiei lambda, aceasta are trei părți principale:
1. Parametrii - reprezintă datele de intrare. În funcție de prezența sau absența parametrilor expresiile pot fi:
a. fără parametri: ()
b. cu un parametru: (x)
c. mai mulți: (x, y)
2. Operatorul lambda -> separă parametri de corpul expresiei și se citește ca ”produce”
3. Corpul expresiei - spune ce face efectiv expresia lambda, adică reprezintă funcționalitatea sau acțiunea expresiei. La fel ca instrucțiunile aceasta poate fi:
a. Simplă: x -> x * 2
b. Compusă: 
x -> {
System.out.println(x);
return x * 2;
}
O expresie lambda nu funcționează singură. Ea trebuie ”legată” de un context unde există o interfață funcțională. De aceea acestea sunt utilizate, în principal, împreună cu interfețe funcționale (precum Runnable, Comparator, Predicate sau una definită de programator) și la lucrul cu colecții de date. 

În această lecție vom vedea cum expresiile lambda ne ajută să lucrăm mai rapid și mai ușor cu listele de date. 

Exemplul 1 Prelucrarea colecțiilor pentru efectuarea operațiilor de filtrare, sortare sau iterarea elementelor colecțiilor.
import java.util.ArrayList;
public class Main
{
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(7);
numbers.add(4);
numbers.add(2);
numbers.add(7);

System.out.println("Afisare elemente folosind lambda expresii");
numbers.forEach( n -> System.out.print(n+" "));
System.out.println("\n-----------------------------------------");

System.out.println("Afisare elementelor a patrat folosind lambda expresii");
numbers.forEach( n -> System.out.print(n*n+" "));
System.out.println("\n-----------------------------------------");

System.out.println("Afisare dacă elementul este > sau < decit 5:");
numbers.forEach(n -> {
if(n < 5)
System.out.println(n + " este mai mic");
else
System.out.println(n + " este mai mare");
});
System.out.println("\n-----------------------------------------");

System.out.println("Afisare elementelor impare folosind lambda expresii");
numbers.forEach( n -> {if (n%2 == 0) System.out.print(n+" ");});
System.out.println("\n-----------------------------------------");

System.out.println("Sortare crescătoare folosind lambda expresii");
numbers.sort((a, b) -> a - b);
numbers.forEach( n -> System.out.print(n+" "));
System.out.println("\n-----------------------------------------");

System.out.println("Sortare descrescătoare folosind lambda expresii");
numbers.sort((a, b) -> b-a);
numbers.forEach( n -> System.out.print(n+" "));
System.out.println("\n-----------------------------------------");

System.out.println("Eliminare elemente duplicat");
numbers.removeIf(n -> numbers.indexOf(n) != numbers.lastIndexOf(n));
numbers.forEach(n -> System.out.print(n + " "));
System.out.println("\n-----------------------------------------");

System.out.println("Sortare crescătoare (text) folosind lambda expresii");
ArrayList<String> persoane = new ArrayList<String>();
persoane.add("Gabriel");
persoane.add("Ion");
persoane.add("Chiril");
persoane.sort((a, b) -> a.compareTo(b));
persoane.forEach(x -> System.out.print(x+" "));
System.out.println("\n-----------------------------------------");

System.out.println("Sortare descrescătoare (text) folosind lambda expresii");
persoane.sort((a, b) -> b.compareTo(a));
persoane.forEach(x -> System.out.print(x+" "));
System.out.println("\n-----------------------------------------\n");
}}

Exemplul 2 Prelucrarea colecțiilor pentru efectuarea deferitor operații de prelucrare a listelor care au ca tip o clasă definită de utilizator
import java.util.ArrayList;
class Elev {
String prenume;
String nume;
public Elev(String prenume, String nume) {
this.prenume = prenume;
this.nume = nume;
}

public String toString() {
return prenume + " " + nume;
}}
public class Main {
public static void main(String[] args) {
ArrayList<Elev> elevi = new ArrayList<>();
elevi.add(new Elev("Ion", "Popescu"));
elevi.add(new Elev("Gabriel", "Ionescu"));
elevi.add(new Elev("Chiril", "Moraru"));
elevi.add(new Elev("Ion", "Albu"));

System.out.println("-----------------------------------------");
System.out.println("Lista inițială:");
elevi.forEach(e -> System.out.println(e));

System.out.println("-----------------------------------------");
System.out.println("Elevi sortati descrescator dupa prenume:");
elevi.sort((e1, e2) -> e1.prenume.compareTo(e2.prenume));
elevi.forEach(e -> System.out.println(e));
System.out.println("-----------------------------------------");

System.out.println("Elevi sortati crescator dupa nume:");
elevi.sort((e1, e2) -> e1.nume.compareTo(e2.nume));
elevi.forEach(e -> System.out.println(e));
System.out.println("-----------------------------------------");

System.out.println("Elevi sortati crescator dupa prenume si nume");
elevi.sort((e1, e2) -> {
int rezultat = e1.prenume.compareTo(e2.prenume);
if (rezultat == 0) {
return e1.nume.compareTo(e2.nume); }
return rezultat;
});
elevi.forEach(e -> System.out.println(e));
System.out.println("-----------------------------------------");

System.out.println("Modificare date elev Popescu Ion in Andrei varianta I:");
elevi.replaceAll(e -> {     
//înocuim înterg obiectul
if(e.prenume.equals("Ion") && e.nume.equals("Popescu"))
return new Elev("Andrei", "Popescu");
return e;
});
elevi.forEach(e -> System.out.println(e));
System.out.println("-----------------------------------------");

System.out.println("Modificare date elev Popescu Andrei in Ion varianta II:");
elevi.forEach(e -> {
if(e.prenume.equals("Andrei") && e.nume.equals("Popescu")) {
e.prenume = "Ion";   
//înlocuim doar câmpul
}
});
elevi.forEach(e -> System.out.println(e));
System.out.println("-----------------------------------------");

System.out.println("Eliminarea elevului Popescu Ion:");
elevi.removeIf(e -> e.prenume.equals("Ion") && e.nume.equals("Popescu"));
elevi.forEach(e -> System.out.println(e));
System.out.println("-----------------------------------------");

System.out.println("Eliminarea elevilor al căror nume incepe cu litera I:");
elevi.removeIf(e -> e.nume.startsWith("i")||e.nume.startsWith("I"));
elevi.forEach(e -> System.out.println(e));
System.out.println("-----------------------------------------");
}}


În compunearea și aplicarea expresiilor lambda vom ține cont de următoarele reguli:
- Dacă expresia lambda nu primește parametri, parantezele sunt obligatorii: () -> 20
- Dacă expresia lambda are un singur parametru, parantezele rotunde pot fi omise: e -> System.out.println(e)
- Dacă expresia lambda are mai mulți parametri atunci parantezele sunt obligatorii: (a, b) -> a.compareTo(b)
- Dacă în interiorul expresiei lambda este o singură instrucțiune atunci cuvântul cheie return nu este obligatoriu de utilizat, la fel ca și acoladele: (e1, e2) -> e1.nume.compareTo(e2.nume)
- Dacă în interiorul expresiei lambda sunt mai multe instrucțiuni atunci cuvântul cheie return este obligatoriu de utilizat, la fel ca și acoladele:
e -> {
if(e.prenume.equals("Ion") && e.nume.equals("Popescu"))
return new Elev("Andrei", "Popescu");
return e;
});
- Lambda poate fi folosită doar acolo unde se așteaptă o interfață funcțională
- Tipul parametrilor poate fi dedus de compilator sau declarat explicit.
- Folosește lambda pentru cod scurt și clar, dacă blocul de cod e lung, poate fi mai lizibil să scrii o metodă separată.
- Evită efectele secundare în lambda (modificarea variabilelor globale), pentru claritate.

Parcurgeți următorul algoritm pentru a decide aveți nevoie de expresii lambda sau nu în contextul proiectului dvs:
De unde știm ce interfață are nevoie expresia lambda ca să funcționeze corect? 
Nu lambda decide tipul de interfață, ci metoda pe care o folosești. De exemplu: 
  • metoda forEach() are nevoie de o acțiune, ea nu returnează valori, aici ar fi ideea că pentru fiecare element din listă fă ceva, o acțiune, de exemplu afișează-l. Expresia lambda în acest caz operează cu interfața Consumer
  • metoda sort() așteaptă o regulă de comparare pentru a aranja anumite elemente într-o anumită ordine. Expresia lambda aici operează cu interfața Comparator
  • metoda removeIf() are nevoie de o condiție pentru a efectua ștergerea și a filtra datele. Aici expresia operează cu interfața Predicate
  • metoda replaceAll() are neoie de o regulă de transformare pentru a înlocui fiecare element din listă cu o versiune modificată a acestuia. Expresia lambda aici operează cu interfața UnaryOperator.  
Putem afla ce interfață acceptă o metodă consultând documentația oficială Java. Aceasta prezintă metodele claselor și, în sintaxa fiecărei metode, interfața corespunzătoare pe care o putem folosi pentru a compune expresia lambda. De exemplu, în documentația clasei ArrayList, metoda removeIf() indică faptul că se poate folosi o expresie lambda care operează cu interfața Predicate:
Este important să reținem că interfața nu știe ce operație va fi aplicată, ea definește doar semnătura metodei, adică tipul de funcție permis, în timp ce lambda specifică exact ce face funcția.

Notă!
Limbajul Java are mai multe interfețe funcționale standard, dar majoritatea sunt limitate la un singur parametru (Function, Consumer, Predicate,ș.a) sau doi parametri (BiFunction, BiConsumer, BiPredicate,ș.a). 
Ca soluție pentru crearea unei expresiilor lambda cu trei și mai mulți parametri se propune:
1. Definirea unei interfețe funcționale proprii.
2. Ambalarea parametrilor într-un obiect și folosirea lambda cu un singur parametru care conține toate valorile.

Dar ...... despre asta vom discuta într-o altă postare.

Dacă această temă v-a trezit un interes mai deosebit vă provoc să studiați amănunțit documentația oficială Java la acest subiect: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#syntax

În contextul lecției curente, dacă ai un exemplu de expresie lambda care se potrivește cu exemplele discutate, te încurajez să-l adaugi în comentarii!

Să aveți o zi deosebită!
❤️