[Java] map과 flatMap의 차이

River Kim·2022년 9월 14일
1

0. 글을 읽기 전

Baeldung 의 The Difference Between map() and flatMap() 문서를 번역(?)하면서 공부한 내용이라 언어만 한글일뿐 내용은 같습니다.

1. 개요

map()flatMap() API는 함수형 언어에서 유래됩니다. Java 8에서는 Optional, StreamCompletableFuture(약간 다른 이름으로)에서 찾을 수 있습니다.

Stream은 일련의 객체를 나타내는 반면 Optional은 존재하거나 없을 수 있는 값을 나타내는 클래스입니다. 다른 집계 작업 중에는 map()flatMap() 메서드가 있습니다.

둘 다 동일한 리턴 타입을 가지고 있음에도 불구하고 상당히 다릅니다.

StreamOptional의 몇 가지 예를 분석하여 이러한 차이점을 설명합니다.

2. Optional의 Map 및 Flatmap

함수가 정확한 타입을 반환하는 경우 map() 메서드는 잘 동작합니다.

Optional<String> s = Optional.of("test");
assertEquals(Optional.of("TEST"), s.map(String::toUpperCase));

그러나 Optional을 리턴하는 더 복잡한 함수가 제공될 수 있습니다.

이런 경우 map() 구현은 내부적으로 추가 래핑을 수행하므로 map()을 사용하면 중첩 구조가 생성됩니다.

이 상황을 더 잘 이해하기 위해 다른 예를 살펴보겠습니다.

assertEquals(Optional.of(Optional.of("STRING)),
  Optional.of("string").map(s -> Optional.of("STRING"))
);

보시다시피 중첩 구조인 Optional<Optional<String>> 으로 끝납니다.
동작하긴 하지만 사용하기가 꽤 번거롭고 추가적인 null 에 대해 안전하지 않으므로 flat한 구조를 유지하는 것이 좋습니다.

이 때 flatMap()을 사용하면 도움이 됩니다.

assertEquals(Optional.of("STRING"),
  Optional.of("string").flatMap(s -> Optional.of("STRING"))
);

3. Stream의 Map 및 Flatmap

Optional과 비슷하게 동작합니다.
map() 메서드는 Stream 인스턴스에서 기본 시퀀스를 래핑하는 반면 flatMap() 메서드는 중첩된 Stream<Stream<R>> 구조를 피할 수 있습니다.

다음 코드에서는 map()Stream의 요소에 toUpperCase() 메서드를 적용한 결과로 구성된 Stream을 생성합니다.

List<String> myList = Stream.of("a", "b")
  .map(String::toUpperCase)
  .collect(Collectors.toList());
assertEquals(asList("A", "B"), myList);

map()은 이러한 간단한 경우에 꽤 잘 작동합니다.

그러나 중첩된 리스트와 같이 입력이 더 복잡할 경우에는 어떻게 될까요?

어떻게 동작하는지 봅시다.

List<List<String>> list = Arrays.asList(
  Arrays.asList("a"),
  Arrays.asList("b")
);
System.out.println(list);

// result: [[a], [b]]

이제 flatMap()을 사용해봅시다.

System.out.println(list
                .stream()
                .flatMap(Collection::stream)
                .toList());

// result: [a, b]

flatMap() 메서드는 먼저 입력 스트림을 문자열 스트림으로 평면화합니다.
이후에는 map() 메서드와 유사하게 동작합니다.

4. 결론

Java 8은 원래 함수형 언어에서 사용되었던 map()flatMap() 메서드를 사용할 수 있는 기회를 제공합니다.
StreamOptional에서 호출할 수 있습니다.
이러한 메서드는 제공된 매핑 기능을 적용하여 매핑된 객체를 가져오는데 도움이 됩니다.

참고문서
https://www.baeldung.com/java-difference-map-and-flatmap

profile
언제까지 개발자로 살 수 있을까..

0개의 댓글