0Pricing
Java Academy · Lezione

Trasformare gli Optional: map e flatMap

Concateni le trasformazioni con map e flatMap per elaborare i valori senza controlli sui valori null.

Trasformare gli Optional: map e flatMap è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

Trasformare gli Optional: map e flatMap

map() trasforma il valore all'interno di un Optional, se presente. flatMap() evita gli Optional annidati quando la trasformazione restituisce a sua volta un Optional.

map: trasformare il valore

map(Function) applica la funzione al valore, se presente, racchiudendo il risultato in un nuovo Optional. Restituisce un Optional vuoto se quello originale era vuoto.

import java.util.Optional;

Optional<String> name = Optional.of("alice");

Optional<String> upper = name.map(String::toUpperCase);
System.out.println(upper.get()); // ALICE

Optional<Integer> length = name.map(String::length);
System.out.println(length.get()); // 5

// Empty in → empty out
Optional<String> empty = Optional.<String>empty().map(String::toUpperCase);
System.out.println(empty.isPresent()); // false

Concatenare chiamate a map

È possibile concatenare più chiamate a map per eseguire le trasformazioni in modo chiaro, senza controlli null annidati.

import java.util.Optional;

record Address(String city, String country) {}
record User(String name, Address address) {}

User user = new User("Alice", new Address("New York", "US"));

// Chain of maps — safe even if any step returns null
Optional<String> city = Optional.ofNullable(user)
    .map(User::address)
    .map(Address::city)
    .map(String::toUpperCase);

System.out.println(city.orElse("Unknown")); // NEW YORK

flatMap: evitare Optional<Optional>

Se la funzione di mapping restituisce Optional, utilizzi flatMap per mantenere un Optional semplice invece di ottenere un Optional<Optional> annidato.

import java.util.Optional;

record User(String name, Optional<String> email) {}

User u = new User("Bob", Optional.of("bob@example.com"));

// map returns Optional<Optional<String>> — ugly!
Optional<Optional<String>> nested = Optional.of(u).map(User::email);

// flatMap flattens: Optional<String>
Optional<String> flat = Optional.of(u).flatMap(User::email);
System.out.println(flat.get()); // bob@example.com

flatMap nella pratica: catena di repository

Un pattern comune consiste nel concatenare ricerche nei repository, ognuna delle quali restituisce un Optional.

import java.util.Optional;

record Order(long id, long userId, double total) {}
record User(long id, String name, String email) {}

static Optional<Order> findOrder(long orderId) {
    return orderId == 1 ? Optional.of(new Order(1, 42, 99.99)) : Optional.empty();
}
static Optional<User> findUser(long userId) {
    return userId == 42 ? Optional.of(new User(42, "Alice", "a@co.com")) : Optional.empty();
}

Optional<String> email = findOrder(1)
    .flatMap(o -> findUser(o.userId()))
    .map(User::email);

System.out.println(email.orElse("Not found")); // a@co.com

Riepilogo delle differenze tra map e flatMap

Come scegliere tra map e flatMap:

  • Utilizzi map quando la funzione restituisce un valore semplice (String, Integer)
  • Utilizzi flatMap quando la funzione restituisce un Optional
import java.util.Optional;

// map: T → R
Optional.of("hello").map(String::toUpperCase);       // Optional<String>
Optional.of("42").map(Integer::parseInt);             // Optional<Integer>

// flatMap: T → Optional<R>
Optional.of("42").flatMap(s -> {
    try { return Optional.of(Integer.parseInt(s)); }
    catch (NumberFormatException e) { return Optional.empty(); }
}); // Optional<Integer> (not Optional<Optional<Integer>>)

Parsing sicuro con flatMap

Un pattern efficace consiste nell'avvolgere in Optional le operazioni rischiose che potrebbero fallire, utilizzando flatMap.

import java.util.Optional;

static Optional<Integer> tryParseInt(String s) {
    try { return Optional.of(Integer.parseInt(s)); }
    catch (NumberFormatException e) { return Optional.empty(); }
}

Optional<String> input = Optional.of("123");
Optional<Integer> parsed = input.flatMap(JavaOptional::tryParseInt);
System.out.println(parsed.map(n -> n * 2).orElse(-1)); // 246

Optional<String> bad = Optional.of("abc");
Optional<Integer> failed = bad.flatMap(JavaOptional::tryParseInt);
System.out.println(failed.orElse(-1)); // -1

Raccogliere gli Optional

Filtri e trasformi uno stream di Optional per raccogliere solo i valori presenti.

import java.util.*;
import java.util.stream.*;

List<String> inputs = List.of("10", "abc", "25", "nope", "7");

List<Integer> numbers = inputs.stream()
    .flatMap(s -> {
        try { return Stream.of(Integer.parseInt(s)); }
        catch (NumberFormatException e) { return Stream.empty(); }
    })
    .collect(Collectors.toList());

System.out.println(numbers); // [10, 25, 7]

Attraversamento di oggetti annidati

map e flatMap rendono sicuro l'attraversamento di grafi di oggetti profondi, senza noiosi controlli su null.

import java.util.Optional;

record Company(String name, Optional<Address> address) {}
record Address(String city, Optional<String> zipCode) {}

Company company = new Company(
    "Acme Corp",
    Optional.of(new Address("Austin", Optional.of("78701")))
);

String zip = Optional.of(company)
    .flatMap(Company::address)
    .flatMap(Address::zipCode)
    .orElse("N/A");

System.out.println(zip); // 78701

map per la conversione dei tipi

map è ideale per convertire il tipo dei valori Optional, ad esempio durante il parsing, la formattazione o l'estrazione di un sotto-campo.

import java.util.Optional;
import java.time.LocalDate;

// Parse a date from String safely
static Optional<LocalDate> parseDate(String s) {
    try { return Optional.of(LocalDate.parse(s)); }
    catch (Exception e) { return Optional.empty(); }
}

Optional<String> dateStr = Optional.of("2024-06-15");
Optional<Integer> year = dateStr
    .flatMap(JavaOptional::parseDate)
    .map(LocalDate::getYear);

System.out.println(year.orElse(-1)); // 2024

Creare pipeline

Combinare filter, map e flatMap consente di creare pipeline di dati espressive, che gestiscono l'assenza a ogni passaggio senza controlli espliciti su null.

import java.util.Optional;

record Product(String sku, String category, boolean inStock, double price) {}

static Optional<Product> findProduct(String sku) {
    if ("LAPTOP-1".equals(sku))
        return Optional.of(new Product("LAPTOP-1", "Electronics", true, 999.99));
    return Optional.empty();
}

Optional<String> priceTag = findProduct("LAPTOP-1")
    .filter(Product::inStock)
    .filter(p -> p.price() < 2000)
    .map(p -> String.format("%s: $%.2f", p.sku(), p.price()));

System.out.println(priceTag.orElse("Not available")); // LAPTOP-1: $999.99

Verifica rapida

Quando è opportuno utilizzare flatMap invece di map su un Optional?

Riepilogo: trasformare gli Optional con map e flatMap

Punti chiave:

  • map() trasforma il valore, se presente, racchiudendo il risultato in un Optional
  • flatMap() è indicato per le funzioni che restituiscono un Optional ed evita gli Optional annidati
  • Concateni più map per eseguire trasformazioni in più passaggi senza controlli su null
  • Utilizzi flatMap per concatenare chiamate a repository o servizi che restituiscono un Optional
  • Combini filter + map + flatMap per creare pipeline di dati sicure rispetto a null
  • Utilizzi flatMap Optional::stream per integrare gli Optional nelle pipeline di stream

Domande Frequenti

La lezione «Trasformare gli Optional: map e flatMap» è gratuita?

Sì — il testo completo di «Trasformare gli Optional: map e flatMap» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «Trasformare gli Optional: map e flatMap»?

Concateni le trasformazioni con map e flatMap per elaborare i valori senza controlli sui valori null. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Trasformare gli Optional: map e flatMap»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Perché esiste Optional
  2. Creazione e ispezione degli Optional
  3. Trasformare gli Optional: map e flatMap
  4. Buone pratiche per Optional
← Torna a Java Academy