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

bookFunzione: Trasformazione Dei Dati

Mentre Predicate ci aiuta a valutare espressioni booleane, Function consente di trasformare i dati applicando operazioni che restituiscono risultati in base all'input.

Function è comunemente utilizzata per la trasformazione dei dati, come la conversione di tipo, calcoli o elaborazione di valori.

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

L'interfaccia Function<T, R> in Java rappresenta un interfaccia funzionale che accetta un argomento di tipo T e restituisce un risultato di tipo R.

Il metodo apply(T t) esegue la trasformazione dei dati prendendo il valore di input e restituendo il risultato. Questo consente di creare funzioni flessibili per elaborare dati di vari tipi.

Applicazione pratica

Supponiamo di avere un elenco di nomi utente e sia necessario calcolare la lunghezza di ciascun nome per successive analisi o elaborazioni dei dati.

Main.java

Main.java

copy
1234567891011121314151617
package com.example; import java.util.Arrays; import java.util.List; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Alice", "Bob", "Charlie", "David"); Function<String, Integer> nameLength = name -> name.length(); users.forEach(user -> { System.out.println(user + " has " + nameLength.apply(user) + " characters."); }); } }

In questo esempio, si dispone di un elenco di nomi utente. Per ciascun nome, si utilizza la funzione nameLength, che calcola il numero di caratteri presenti nel nome utilizzando il metodo length(). Utilizzando il metodo forEach, si itera su ogni elemento dell'elenco e si stampa un messaggio che mostra quanti caratteri contiene ciascun nome.

Combinazione di funzioni

L'interfaccia Function fornisce diversi metodi per la combinazione di funzioni, consentendo di creare una catena di operazioni.

Metodo andThen()

Il metodo andThen() consente di combinare due funzioni applicando prima una funzione e poi passando il risultato alla seconda funzione. Questo è utile quando è necessario eseguire più operazioni in sequenza.

Esempio

Si dispone di un elenco di nomi utente e si deve maiuscolizzare la prima lettera di ciascun nome e poi verificare se il nome contiene più di 5 caratteri.

Main.java

Main.java

copy
1234567891011121314151617181920212223
package com.example; import java.util.Arrays; import java.util.List; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> usernames = Arrays.asList("john", "alice", "bob", "charlie", "david"); // Capitalize first letter Function<String, String> capitalizeFirstLetter = name -> name.substring(0, 1).toUpperCase() + name.substring(1); // Check if the username has more than 5 characters Function<String, Boolean> isLongerThanFive = name -> name.length() > 5; // Combine functions using `andThen()` Function<String, Boolean> formattedNameThenCheckLength = capitalizeFirstLetter.andThen(isLongerThanFive); usernames.forEach(user -> { System.out.println(user + " -> " + formattedNameThenCheckLength.apply(user)); }); } }

Per prima cosa si maiuscolizza la prima lettera di ogni nome utente utilizzando capitalizeFirstLetter. Successivamente, si verifica se il nome formattato contiene più di 5 caratteri tramite isLongerThanFive. Le due funzioni vengono combinate tramite andThen() per una elaborazione sequenziale.

Metodo compose()

Il metodo compose() consente di combinare funzioni, ma in ordine inverso: la seconda funzione viene applicata per prima e il risultato viene poi passato alla prima funzione.

Esempio

Si dispone di una stringa e si desidera prima calcolarne la lunghezza e poi aggiungere un prefisso al risultato.

Main.java

Main.java

copy
123456789101112131415161718
package com.example; import java.util.function.Function; public class Main { public static void main(String[] args) { String phrase = "Hello World"; // First, calculate the length, then add a prefix Function<String, Integer> stringLength = String::length; Function<Integer, String> addPrefix = length -> "Length: " + length; // Combine functions using compose Function<String, String> lengthThenPrefix = addPrefix.compose(stringLength); System.out.println(lengthThenPrefix.apply(phrase)); // Output: Length: 11 } }

In questo esempio, si calcola prima la lunghezza della stringa utilizzando stringLength, e poi il risultato viene passato alla funzione addPrefix, che aggiunge un prefisso. Si utilizza compose() per applicare le funzioni nell'ordine desiderato.

Metodo identity()

Il metodo identity() restituisce una funzione che semplicemente restituisce il proprio argomento senza alcuna modifica. Questo è utile quando è necessario passare una funzione che non modifica il valore di input ma è richiesta per rispettare l'interfaccia.

Esempio

Si immagini di dover elaborare un elenco di nomi utente applicando diverse trasformazioni: una per convertire i nomi in maiuscolo, un'altra per aggiungere il suffisso "User", e una terza utilizzando la funzione identity() per lasciare il nome inalterato. L'obiettivo è applicare queste funzioni a ciascun nome nell'elenco mantenendo coerente l'interfaccia del programma per ogni trasformazione.

Main.java

Main.java

copy
1234567891011121314151617181920212223242526272829303132
package com.example; import java.util.List; import java.util.Arrays; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> usernames = Arrays.asList("alice", "bob", "charlie", "david", "eve"); // `Function` to convert the username to uppercase Function<String, String> uppercaseFunction = name -> name.toUpperCase(); // `Function` to add the "User" suffix Function<String, String> suffixFunction = name -> name + "User"; // Identity `Function`, which does nothing Function<String, String> identityFunction = Function.identity(); // Applying a combination of functions List<Function<String, ?>> transformations = Arrays.asList(uppercaseFunction, suffixFunction, identityFunction); // Applying each `Function` from the list for (Function<String, ?> transformation : transformations) { System.out.println("--------------------"); usernames.stream() .map(name -> transformation.apply(name)) .forEach(System.out::println); } } }

Come puoi vedere, l'output consiste in tre elenchi formattati di nomi utente. L'ultimo elenco contiene i nomi originali, ed è qui che il metodo identity() risulta utile, poiché consente di restituire i nomi senza aggiungere logica extra per gestire i valori invariati. Questo rende il codice più pulito e più efficiente utilizzando direttamente identity() quando non è necessaria alcuna trasformazione.

1. Cosa fa il metodo andThen() nell'interfaccia Function?

2. Quale sarà il risultato dell'applicazione del metodo identity()?

3. Cosa fa il metodo compose()?

question mark

Cosa fa il metodo andThen() nell'interfaccia Function?

Select the correct answer

question mark

Quale sarà il risultato dell'applicazione del metodo identity()?

Select the correct answer

question mark

Cosa fa il metodo compose()?

Select the correct answer

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 1. Capitolo 6

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

bookFunzione: Trasformazione Dei Dati

Scorri per mostrare il menu

Mentre Predicate ci aiuta a valutare espressioni booleane, Function consente di trasformare i dati applicando operazioni che restituiscono risultati in base all'input.

Function è comunemente utilizzata per la trasformazione dei dati, come la conversione di tipo, calcoli o elaborazione di valori.

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

L'interfaccia Function<T, R> in Java rappresenta un interfaccia funzionale che accetta un argomento di tipo T e restituisce un risultato di tipo R.

Il metodo apply(T t) esegue la trasformazione dei dati prendendo il valore di input e restituendo il risultato. Questo consente di creare funzioni flessibili per elaborare dati di vari tipi.

Applicazione pratica

Supponiamo di avere un elenco di nomi utente e sia necessario calcolare la lunghezza di ciascun nome per successive analisi o elaborazioni dei dati.

Main.java

Main.java

copy
1234567891011121314151617
package com.example; import java.util.Arrays; import java.util.List; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Alice", "Bob", "Charlie", "David"); Function<String, Integer> nameLength = name -> name.length(); users.forEach(user -> { System.out.println(user + " has " + nameLength.apply(user) + " characters."); }); } }

In questo esempio, si dispone di un elenco di nomi utente. Per ciascun nome, si utilizza la funzione nameLength, che calcola il numero di caratteri presenti nel nome utilizzando il metodo length(). Utilizzando il metodo forEach, si itera su ogni elemento dell'elenco e si stampa un messaggio che mostra quanti caratteri contiene ciascun nome.

Combinazione di funzioni

L'interfaccia Function fornisce diversi metodi per la combinazione di funzioni, consentendo di creare una catena di operazioni.

Metodo andThen()

Il metodo andThen() consente di combinare due funzioni applicando prima una funzione e poi passando il risultato alla seconda funzione. Questo è utile quando è necessario eseguire più operazioni in sequenza.

Esempio

Si dispone di un elenco di nomi utente e si deve maiuscolizzare la prima lettera di ciascun nome e poi verificare se il nome contiene più di 5 caratteri.

Main.java

Main.java

copy
1234567891011121314151617181920212223
package com.example; import java.util.Arrays; import java.util.List; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> usernames = Arrays.asList("john", "alice", "bob", "charlie", "david"); // Capitalize first letter Function<String, String> capitalizeFirstLetter = name -> name.substring(0, 1).toUpperCase() + name.substring(1); // Check if the username has more than 5 characters Function<String, Boolean> isLongerThanFive = name -> name.length() > 5; // Combine functions using `andThen()` Function<String, Boolean> formattedNameThenCheckLength = capitalizeFirstLetter.andThen(isLongerThanFive); usernames.forEach(user -> { System.out.println(user + " -> " + formattedNameThenCheckLength.apply(user)); }); } }

Per prima cosa si maiuscolizza la prima lettera di ogni nome utente utilizzando capitalizeFirstLetter. Successivamente, si verifica se il nome formattato contiene più di 5 caratteri tramite isLongerThanFive. Le due funzioni vengono combinate tramite andThen() per una elaborazione sequenziale.

Metodo compose()

Il metodo compose() consente di combinare funzioni, ma in ordine inverso: la seconda funzione viene applicata per prima e il risultato viene poi passato alla prima funzione.

Esempio

Si dispone di una stringa e si desidera prima calcolarne la lunghezza e poi aggiungere un prefisso al risultato.

Main.java

Main.java

copy
123456789101112131415161718
package com.example; import java.util.function.Function; public class Main { public static void main(String[] args) { String phrase = "Hello World"; // First, calculate the length, then add a prefix Function<String, Integer> stringLength = String::length; Function<Integer, String> addPrefix = length -> "Length: " + length; // Combine functions using compose Function<String, String> lengthThenPrefix = addPrefix.compose(stringLength); System.out.println(lengthThenPrefix.apply(phrase)); // Output: Length: 11 } }

In questo esempio, si calcola prima la lunghezza della stringa utilizzando stringLength, e poi il risultato viene passato alla funzione addPrefix, che aggiunge un prefisso. Si utilizza compose() per applicare le funzioni nell'ordine desiderato.

Metodo identity()

Il metodo identity() restituisce una funzione che semplicemente restituisce il proprio argomento senza alcuna modifica. Questo è utile quando è necessario passare una funzione che non modifica il valore di input ma è richiesta per rispettare l'interfaccia.

Esempio

Si immagini di dover elaborare un elenco di nomi utente applicando diverse trasformazioni: una per convertire i nomi in maiuscolo, un'altra per aggiungere il suffisso "User", e una terza utilizzando la funzione identity() per lasciare il nome inalterato. L'obiettivo è applicare queste funzioni a ciascun nome nell'elenco mantenendo coerente l'interfaccia del programma per ogni trasformazione.

Main.java

Main.java

copy
1234567891011121314151617181920212223242526272829303132
package com.example; import java.util.List; import java.util.Arrays; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> usernames = Arrays.asList("alice", "bob", "charlie", "david", "eve"); // `Function` to convert the username to uppercase Function<String, String> uppercaseFunction = name -> name.toUpperCase(); // `Function` to add the "User" suffix Function<String, String> suffixFunction = name -> name + "User"; // Identity `Function`, which does nothing Function<String, String> identityFunction = Function.identity(); // Applying a combination of functions List<Function<String, ?>> transformations = Arrays.asList(uppercaseFunction, suffixFunction, identityFunction); // Applying each `Function` from the list for (Function<String, ?> transformation : transformations) { System.out.println("--------------------"); usernames.stream() .map(name -> transformation.apply(name)) .forEach(System.out::println); } } }

Come puoi vedere, l'output consiste in tre elenchi formattati di nomi utente. L'ultimo elenco contiene i nomi originali, ed è qui che il metodo identity() risulta utile, poiché consente di restituire i nomi senza aggiungere logica extra per gestire i valori invariati. Questo rende il codice più pulito e più efficiente utilizzando direttamente identity() quando non è necessaria alcuna trasformazione.

1. Cosa fa il metodo andThen() nell'interfaccia Function?

2. Quale sarà il risultato dell'applicazione del metodo identity()?

3. Cosa fa il metodo compose()?

question mark

Cosa fa il metodo andThen() nell'interfaccia Function?

Select the correct answer

question mark

Quale sarà il risultato dell'applicazione del metodo identity()?

Select the correct answer

question mark

Cosa fa il metodo compose()?

Select the correct answer

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 1. Capitolo 6
some-alt