1. Espressioni Lambda
Un'espressione lambda è una funzione anonima che consente di scrivere codice funzionale in Java.
Può essere utilizzata per passare il comportamento come argomento a un metodo o per implementare metodi di interfacce funzionali in modo conciso.
Sintassi
La sintassi base di un'espressione lambda è la seguente:
(parametri) -> { corpo }
Parametri
: Specificano i valori in ingresso. Se c'è un solo parametro, le parentesi possono essere omesse.
Freccia
(->): Separa i parametri dal corpo della lambda.
Corpo
: Contiene il codice eseguito dall'espressione lambda.
Esempi
- Lambda con un parametro:
Consumer<String> stampa = s -> System.out.println(s); stampa.accept("Hello, Lambda!");
- Lambda con più parametri:
BiFunction<Integer, Integer, Integer> somma = (a, b) -> a + b; System.out.println(somma.apply(5, 3)); // Output: 8
- Lambda con corpo complesso:
Comparator<Integer> comparatore = (a, b) -> { if (a > b) return 1; else if (a < b) return -1; else return 0; };
Interfacce Funzionali
Un'espressione lambda richiede un'interfaccia funzionale, ossia un'interfaccia con un solo metodo astratto.
Runnable
(senza ritorno):
Runnable runnable = () -> System.out.println("Esecuzione in corso..."); runnable.run();
Function<T, R>
(un parametro, un valore di ritorno):
Function<String, Integer> lunghezza = s -> s.length(); System.out.println(lunghezza.apply("Lambda")); // Output: 6
2. Stream
Le Stream API permettono di elaborare collezioni di dati in modo funzionale e dichiarativo. Con gli stream è possibile
filtrare
, trasformare
, ordinare
e ridurre
i dati in maniera efficiente.Creazione di uno Stream
Uno stream può essere creato da diverse sorgenti, come liste, array o file:
import java.util.stream.*; List<String> nomi = Arrays.asList("Anna", "Luca", "Marco"); Stream<String> stream = nomi.stream();
Operazioni su uno Stream
Gli stream supportano due tipi di operazioni:
- Operazioni intermedie: Restituiscono uno stream e possono essere concatenate.
- Operazioni terminali: Restituiscono un risultato e terminano lo stream.
Operazioni Intermedie
filter()
: Filtra elementi in base a una condizione.
List<String> filtrati = nomi.stream() .filter(nome -> nome.startsWith("M")) .collect(Collectors.toList()); System.out.println(filtrati); // Output: [Marco]
map()
: Trasforma ogni elemento.
List<Integer> lunghezze = nomi.stream() .map(String::length) .collect(Collectors.toList()); System.out.println(lunghezze); // Output: [4, 4, 5]
sorted()
: Ordina gli elementi.
List<String> ordinati = nomi.stream() .sorted() .collect(Collectors.toList()); System.out.println(ordinati); // Output: [Anna, Luca, Marco]
distinct()
: Rimuove duplicati.
List<Integer> unici = Arrays.asList(1, 2, 2, 3, 3, 4).stream() .distinct() .collect(Collectors.toList()); System.out.println(unici); // Output: [1, 2, 3, 4]
Operazioni Terminali
collect()
: Converte uno stream in una collezione.
List<String> lista = nomi.stream() .collect(Collectors.toList());
forEach()
: Itera sugli elementi.
nomi.stream().forEach(System.out::println);
reduce()
: Combina gli elementi in un unico risultato.
int somma = Arrays.asList(1, 2, 3, 4).stream() .reduce(0, Integer::sum); System.out.println(somma); // Output: 10
- count(): Conta gli elementi.
long conteggio = nomi.stream().count(); System.out.println(conteggio); // Output: 3
anyMatch()
,allMatch()
,noneMatch()
: Testano condizioni sugli elementi.
boolean esisteMarco = nomi.stream().anyMatch(nome -> nome.equals("Marco")); System.out.println(esisteMarco); // Output: true