Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Impara Principi | Fondamenti e Capacità Funzionali dello Stream API
Stream API

bookPrincipi

I principi di utilizzo della Stream API si basano su concetti chiave della programmazione funzionale e della valutazione pigra. Analizziamo i principali principi della Stream API.

Valutazione Pigra

Uno dei principali principi della Stream API è la valutazione pigra.

Questo significa che le operazioni intermedie come filter() o map() non vengono eseguite immediatamente. Esse formano semplicemente una catena di azioni che verranno eseguite solo quando viene invocata un'operazione terminale, come collect() o forEach().

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); long count = names.stream() .filter(name -> name.startsWith("A")) // Forming the operation .count(); // Triggering execution System.out.println(count); // Output: 1 } }

Questo codice crea uno stream da una lista di stringhe, filtra gli elementi per mantenere solo quelli che iniziano con la lettera A e conta quanti soddisfano la condizione. Il risultato (1) viene stampato poiché solo Alice soddisfa la condizione.

Stile di programmazione funzionale

La Stream API utilizza espressioni lambda e interfacce funzionali per l'elaborazione dei dati. Invece dell'approccio imperativo con i cicli, si descrive cosa deve essere fatto con i dati:

Main.java

Main.java

copy
1234567891011121314
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> fruits = List.of("apple", "banana", "cherry", "apricot", "blueberry"); List<String> result = fruits.stream() .map(String::toUpperCase) // Convert all strings to uppercase .skip(3) .toList(); // Collect the result into a new list System.out.println(result); } }

Questo codice crea uno stream da una lista di frutti, converte le stringhe in maiuscolo usando map(), e salta i primi tre elementi con skip(). Il risultato viene raccolto in una nuova lista e stampato, a partire dal quarto elemento.

Immutabilità dei dati

La Stream API non modifica i dati originali. Tutte le operazioni creano un nuovo stream o restituiscono un risultato senza modificare la collezione o l'array. Questo aumenta la sicurezza dei dati e previene effetti collaterali inattesi.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); List<String> updateNames = names.stream() .filter(name -> name.startsWith("A")) .toList(); System.out.println(names); // Output: [Alice, Bob, Charlie] } }

La Stream API filtra la lista dei nomi per creare un nuovo stream, updateNames, che contiene solo gli elementi che iniziano con la lettera A. Tuttavia, la lista originale dei nomi rimane invariata, poiché la Stream API non modifica direttamente i dati, garantendo la sicurezza dei dati e prevenendo effetti collaterali.

Gli stream sono consumabili una sola volta

Uno stream può essere utilizzato solo una volta. Dopo che viene eseguita un'operazione terminale, lo stream non è più disponibile per ulteriori elaborazioni.

Main.java

Main.java

copy
123456789101112
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream<String> stream = List.of("Alice", "Bob").stream(); stream.forEach(System.out::println); stream.forEach(System.out::println); // Error: Stream has already been used } }

Qui viene creato uno stream da una lista di stringhe e ogni elemento viene stampato sulla console. Dopo che lo stream è stato utilizzato per la prima volta, non può essere riutilizzato, il che causa un errore se si tenta di chiamare nuovamente forEach().

Elaborazione parallela

La Stream API supporta gli stream paralleli, consentendo una elaborazione dei dati più veloce su sistemi multi-core. Questo argomento viene approfondito qui

Main.java

Main.java

copy
1234567891011
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = List.of(1, 2, 3, 4, 5); numbers.parallelStream() .forEach(System.out::println); // Elements are processed in parallel } }

Questo codice crea uno stream parallelo da una lista di numeri e stampa ogni elemento sulla console. L'utilizzo di parallelStream() consente l'elaborazione parallela degli elementi della lista, il che può velocizzare l'esecuzione quando si lavora con grandi insiemi di dati.

Pulizia e leggibilità del codice

L'utilizzo della Stream API rende il codice più dichiarativo. Invece di descrivere come eseguire un compito (come con i cicli), si descrive cosa deve essere fatto. Questo migliora la leggibilità e semplifica la manutenzione del codice.

Esempio con un ciclo:

List<String> names = List.of("Alice", "Bob", "Charlie");
for (String name : names) {
    System.out.println(name);
}

Esempio di utilizzo della Stream API:

List<String> names = List.of("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);

Nel primo esempio con il ciclo, si descrive esplicitamente come iterare sulla lista e stampare gli elementi, mentre nel secondo esempio con la Stream API si specifica semplicemente cosa deve essere fatto: iterare sugli elementi e stampare. Questo rende il codice più dichiarativo e leggibile.

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 1. Capitolo 2

Chieda ad AI

expand

Chieda ad AI

ChatGPT

Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione

Awesome!

Completion rate improved to 2.33

bookPrincipi

Scorri per mostrare il menu

I principi di utilizzo della Stream API si basano su concetti chiave della programmazione funzionale e della valutazione pigra. Analizziamo i principali principi della Stream API.

Valutazione Pigra

Uno dei principali principi della Stream API è la valutazione pigra.

Questo significa che le operazioni intermedie come filter() o map() non vengono eseguite immediatamente. Esse formano semplicemente una catena di azioni che verranno eseguite solo quando viene invocata un'operazione terminale, come collect() o forEach().

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); long count = names.stream() .filter(name -> name.startsWith("A")) // Forming the operation .count(); // Triggering execution System.out.println(count); // Output: 1 } }

Questo codice crea uno stream da una lista di stringhe, filtra gli elementi per mantenere solo quelli che iniziano con la lettera A e conta quanti soddisfano la condizione. Il risultato (1) viene stampato poiché solo Alice soddisfa la condizione.

Stile di programmazione funzionale

La Stream API utilizza espressioni lambda e interfacce funzionali per l'elaborazione dei dati. Invece dell'approccio imperativo con i cicli, si descrive cosa deve essere fatto con i dati:

Main.java

Main.java

copy
1234567891011121314
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> fruits = List.of("apple", "banana", "cherry", "apricot", "blueberry"); List<String> result = fruits.stream() .map(String::toUpperCase) // Convert all strings to uppercase .skip(3) .toList(); // Collect the result into a new list System.out.println(result); } }

Questo codice crea uno stream da una lista di frutti, converte le stringhe in maiuscolo usando map(), e salta i primi tre elementi con skip(). Il risultato viene raccolto in una nuova lista e stampato, a partire dal quarto elemento.

Immutabilità dei dati

La Stream API non modifica i dati originali. Tutte le operazioni creano un nuovo stream o restituiscono un risultato senza modificare la collezione o l'array. Questo aumenta la sicurezza dei dati e previene effetti collaterali inattesi.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); List<String> updateNames = names.stream() .filter(name -> name.startsWith("A")) .toList(); System.out.println(names); // Output: [Alice, Bob, Charlie] } }

La Stream API filtra la lista dei nomi per creare un nuovo stream, updateNames, che contiene solo gli elementi che iniziano con la lettera A. Tuttavia, la lista originale dei nomi rimane invariata, poiché la Stream API non modifica direttamente i dati, garantendo la sicurezza dei dati e prevenendo effetti collaterali.

Gli stream sono consumabili una sola volta

Uno stream può essere utilizzato solo una volta. Dopo che viene eseguita un'operazione terminale, lo stream non è più disponibile per ulteriori elaborazioni.

Main.java

Main.java

copy
123456789101112
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream<String> stream = List.of("Alice", "Bob").stream(); stream.forEach(System.out::println); stream.forEach(System.out::println); // Error: Stream has already been used } }

Qui viene creato uno stream da una lista di stringhe e ogni elemento viene stampato sulla console. Dopo che lo stream è stato utilizzato per la prima volta, non può essere riutilizzato, il che causa un errore se si tenta di chiamare nuovamente forEach().

Elaborazione parallela

La Stream API supporta gli stream paralleli, consentendo una elaborazione dei dati più veloce su sistemi multi-core. Questo argomento viene approfondito qui

Main.java

Main.java

copy
1234567891011
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = List.of(1, 2, 3, 4, 5); numbers.parallelStream() .forEach(System.out::println); // Elements are processed in parallel } }

Questo codice crea uno stream parallelo da una lista di numeri e stampa ogni elemento sulla console. L'utilizzo di parallelStream() consente l'elaborazione parallela degli elementi della lista, il che può velocizzare l'esecuzione quando si lavora con grandi insiemi di dati.

Pulizia e leggibilità del codice

L'utilizzo della Stream API rende il codice più dichiarativo. Invece di descrivere come eseguire un compito (come con i cicli), si descrive cosa deve essere fatto. Questo migliora la leggibilità e semplifica la manutenzione del codice.

Esempio con un ciclo:

List<String> names = List.of("Alice", "Bob", "Charlie");
for (String name : names) {
    System.out.println(name);
}

Esempio di utilizzo della Stream API:

List<String> names = List.of("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);

Nel primo esempio con il ciclo, si descrive esplicitamente come iterare sulla lista e stampare gli elementi, mentre nel secondo esempio con la Stream API si specifica semplicemente cosa deve essere fatto: iterare sugli elementi e stampare. Questo rende il codice più dichiarativo e leggibile.

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 1. Capitolo 2
some-alt