Transformação de Optionals: map e flatMap
Encadeie transformações com map e flatMap para processar valores sem verificações de nulos.
Transformação de Optionals: map e flatMap é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
Transformando Optionals: map e flatMap
map() transforma o valor dentro de um Optional se ele estiver presente. flatMap() evita Optionals aninhados quando a própria transformação retorna um Optional.
map: transformando o valor
map(Function) aplica a função ao valor se ele estiver presente, encapsulando o resultado em um novo Optional. Retorna vazio se o Optional original estiver vazio.
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()); // falseEncadeando chamadas map
Várias chamadas de map encadeiam transformações de forma limpa, sem verificações de null aninhadas.
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 YORKflatMap: evitando Optional<Optional>
Se sua função de mapeamento retornar Optional, use flatMap para manter um Optional simples em vez de um Optional<Optional> aninhado.
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.comflatMap na prática: cadeia de repositórios
Um padrão comum: encadear buscas em repositórios nas quais cada uma retorna 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.comResumo de map e flatMap
Escolhendo entre map e flatMap:
- Use
mapquando a função retornar um valor simples (String, inteiro) - Use
flatMapquando a função retornar um 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>>)Análise segura com flatMap
Um padrão elegante: encapsular operações arriscadas que podem falhar em Optional usando 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)); // -1Coletando Optionals
Filtre e mapeie um fluxo de Optionals para coletar somente os valores presentes.
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]Percurso de objetos aninhados
map e flatMap tornam seguro percorrer grafos profundos de objetos sem verificações de null tediosas.
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); // 78701map para conversão de tipos
map é excelente para converter os tipos de valores Optional — por exemplo, analisar, formatar ou extrair um subcampo.
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)); // 2024Criando fluxos de processamento
Combinar filter, map e flatMap cria fluxos de dados expressivos que tratam a ausência em cada etapa sem verificações explícitas de 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.99Verificação rápida
Quando você deve usar flatMap em vez de map em um Optional?
Recapitulação: transformando Optionals: map e flatMap
Principais conclusões:
- map() transforma o valor quando ele está presente, encapsulando o resultado em um Optional
- flatMap() é usado para funções que retornam Optional — evitando Optionals aninhados
- Encadeie vários maps para realizar transformações em várias etapas sem verificações de null
- Use flatMap para encadear chamadas de repositório ou serviço que retornam Optional
- Combine filter + map + flatMap para criar fluxos de dados seguros contra null
- Use flatMap Optional::stream para incorporar Optionals a fluxos de processamento
Perguntas Frequentes
A aula “Transformação de Optionals: map e flatMap” é grátis?
Sim — o texto completo de “Transformação de Optionals: map e flatMap” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “Transformação de Optionals: map e flatMap”?
Encadeie transformações com map e flatMap para processar valores sem verificações de nulos. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Transformação de Optionals: map e flatMap”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que Optional Existe
- Criação e Inspeção de Optionals
- Transformação de Optionals: map e flatMap
- Boas Práticas com Optional