0Pricing
Java Academy · 강의

Optional 변환: map과 flatMap

null 검사 없이 값을 처리하도록 map과 flatMap으로 변환을 연결합니다.

Optional 변환: map과 flatMap은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

Optional 변환하기: map과 flatMap

map()은 Optional에 값이 있으면 그 안의 값을 변환합니다. flatMap()은 변환 자체가 Optional을 반환할 때 중첩 Optional이 생기는 것을 방지합니다.

map: 값 변환하기

map(Function)은 값이 있으면 해당 값에 함수를 적용하고, 결과를 새 Optional로 감쌉니다. 원래 Optional이 비어 있으면 비어 있는 Optional을 반환합니다.

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

map 호출 연결하기

여러 map 호출을 연결하면 중첩된 null 확인 없이 변환을 깔끔하게 이어 갈 수 있습니다.

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: Optional<Optional> 피하기

매핑 함수가 Optional을 반환한다면 flatMap을 사용하여 중첩된 Optional<Optional> 대신 평평한 Optional을 유지하십시오.

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: 저장소 연결

각 조회가 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

map과 flatMap 요약

map과 flatMap 중 선택하는 기준은 다음과 같습니다.

  • 함수가 일반 값(String, Integer)을 반환하면 map을 사용하십시오
  • 함수가 Optional을 반환하면 flatMap을 사용하십시오
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>>)

flatMap을 사용한 안전한 파싱

실패할 수 있는 위험한 작업을 flatMap을 사용하여 Optional로 감싸는 유용한 패턴입니다.

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

Optional 수집하기

Optional 스트림을 필터링하고 매핑하여 값이 있는 항목만 수집하십시오.

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]

중첩 객체 탐색

map과 flatMap을 사용하면 번거로운 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 사용하기

map은 Optional 값의 형식을 변환할 때 유용합니다. 예를 들어 파싱, 형식 지정 또는 하위 필드 추출에 사용할 수 있습니다.

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

파이프라인 구성하기

filter, map 및 flatMap을 결합하면 각 단계에서 값의 부재를 명시적인 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

빠른 확인

Optional에서 map 대신 flatMap을 사용해야 하는 경우는 언제입니까?

복습: Optional 변환하기: map과 flatMap

핵심 내용:

  • map()은 값이 있으면 값을 변환하고 결과를 Optional로 감쌉니다
  • flatMap()은 Optional을 반환하는 함수에 사용하며, 중첩 Optional을 방지합니다
  • null 확인 없이 여러 단계의 변환을 수행하려면 여러 map을 연결하십시오
  • Optional을 반환하는 저장소/서비스 호출을 연결하려면 flatMap을 사용하십시오
  • filter + map + flatMap을 결합하여 null에 안전한 데이터 파이프라인을 구성하십시오
  • flatMap Optional::stream을 사용하여 Optional을 스트림 파이프라인에 포함하십시오

자주 묻는 질문

“Optional 변환: map과 flatMap” 강의는 무료인가요?

네 — “Optional 변환: map과 flatMap” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“Optional 변환: map과 flatMap”에서 뭘 배우나요?

null 검사 없이 값을 처리하도록 map과 flatMap으로 변환을 연결합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“Optional 변환: map과 flatMap” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Optional이 존재하는 이유
  2. Optional 생성과 검사
  3. Optional 변환: map과 flatMap
  4. Optional 모범 사례
← Java Academy(으)로 돌아가기