Optional.map în Java

map transformă valoarea din Optional (dacă există) și o pune într-un Optional nou; flatMap face la fel pentru funcții care returnează deja Optional.

Sintaxă
<U> Optional<U> map(Function<? super T, ? extends U> mapper)
<U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)

Ce face Optional.map

o.map(f) aplică f pe valoare și returnează un Optional cu rezultatul. Dacă o e gol, f nu se apelează și primești un Optional gol. Dacă f returnează null, rezultatul este tot gol. Astfel poți înlănțui pași fără verificări de null.

flatMap se folosește când funcția returnează ea însăși un Optional. Cu map ai obține Optional<Optional<U>>; flatMap „aplatizează” rezultatul la Optional<U>.

Parametri

Parametru Descriere
mapper Funcția de transformare.

Ce returnează

Un Optional nou, cu rezultatul sau gol.

Exemple

Exemplul 1: Lungimea unui nume care poate lipsi

import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        Optional<String> nume = Optional.of("Alexandra");
        Optional<String> lipsa = Optional.empty();
        System.out.println(nume.map(String::length));
        System.out.println(lipsa.map(String::length));
        System.out.println(nume.map(String::toUpperCase).map(s -> s.charAt(0)).orElse('?'));
    }
}

Rezultat

Optional[9]
Optional.empty
A

Exemplul 2: flatMap pentru metode care returnează Optional

Fiecare pas poate eșua și returnează Optional. Cu flatMap lanțul rămâne Optional<String>.

import java.util.Map;
import java.util.Optional;

public class Main {
    static final Map<String, String> clientLaOras = Map.of("Ana", "Iași", "Radu", "Sibiu");
    static final Map<String, String> orasLaDepozit = Map.of("Iași", "Depozit Moldova");

    static Optional<String> oras(String client) {
        return Optional.ofNullable(clientLaOras.get(client));
    }

    static Optional<String> depozit(String oras) {
        return Optional.ofNullable(orasLaDepozit.get(oras));
    }

    public static void main(String[] args) {
        for (String client : new String[] {"Ana", "Radu", "Elena"}) {
            String d = oras(client).flatMap(Main::depozit).orElse("livrare prin curier");
            System.out.println(client + ": " + d);
        }
    }
}

Rezultat

Ana: Depozit Moldova
Radu: livrare prin curier
Elena: livrare prin curier

Greșeli frecvente

  • Folosești map cu o funcție care returnează Optional și primești Optional<Optional<...>>. Folosește flatMap.
  • Folosești map doar pentru efecte (afișare). Pentru asta există ifPresent.

Comenzi înrudite

  • Optional: O „cutie” care conține o valoare sau este goală. Arată clar că un rezultat poate lipsi și te obligă să tratezi cazul, în loc de null.
  • Optional.filter: Păstrează valoarea din Optional doar dacă îndeplinește o condiție; altfel returnează un Optional gol.
  • Optional.orElse: orElse returnează valoarea sau o rezervă dată; orElseGet calculează rezerva cu o funcție, doar când e nevoie.
  • Stream.map: Transformă fiecare element al stream-ului în altă valoare, eventual de alt tip.
  • Stream.flatMap: Transformă fiecare element într-un stream și lipește toate aceste stream-uri într-unul singur.