728x90
Java의 Stream API는 데이터를 함수형 스타일로 처리할 수 있는 강력한 도구다.
그중에서도 `map()`과 `flatMap()`은 가장 자주 사용되는 중간 연산자이다.
하지만 두 메서드는 이름이 비슷해 헷갈리기 쉽다.
이번 글에서는 두 메서드의 차이와 활용법을 예제 중심으로 쉽게 정리해보겠다.
🔄 map() - 요소를 변환
`map()`은 스트림의 각 요소를 일대일로 변환할 때 사용한다.
주로 원하는 필드만 추출하거나 특정 형태로 변환할 떄 사용한다.
예시)
- 각 요소를 새로운 값으로 매핑
- 변환 결과를 새 스트림으로 반환
- 내부적으로 `Function<T, R>`이 사용됨
📌 예제 1: 문자열을 대문자로
List<String> names = Arrays.asList("kimcoding", "javalee", "hackerna", "luckyguy");
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
출력:
KIMCODING
JAVALEE
HACKERNA
LUCKYGUY
📌 예제 2: 숫자 변환
List<Integer> numbers = Arrays.asList(1, 3, 6, 9);
numbers.stream()
.map(n -> n * 3)
.forEach(System.out::println);
출력:
3
9
18
27
📂 flatMap() - 중첩을 펼치다
`flatMap()`은 중첩된 스트림의 구조를 스트림의 각 요소를 스트림으로 변환하여
그 모든 내부 스트림을 하나로 평탄화(flatten) 한다.
- 중첩된 구조 해제 (2차원 → 1차원)
- `Stream<Stream<T>> → Stream<T>`
- 내부적으로 `Function<T, Stream<R>>` 사용
📌 예제: 중첩 리스트 평탄화
List<List<String>> nestedList = Arrays.asList(
Arrays.asList("JAVA", "SPRING"),
Arrays.asList("java", "spring")
);
nestedList.stream()
.flatMap(Collection::stream)
.forEach(System.out::println);
출력:
JAVA
SPRING
java
spring
🧠 map() vs flatMap()의 차이점
같은 데이터로 두 방식 비교해보자!
List<String> sentences = Arrays.asList("a b", "c d");
// map 사용
List<Stream<String>> withMap = sentences.stream()
.map(s -> Arrays.stream(s.split(" "))) // Stream<Stream<String>>
.collect(Collectors.toList());
// flatMap 사용
List<String> withFlatMap = sentences.stream()
.flatMap(s -> Arrays.stream(s.split(" "))) // Stream<String>
.collect(Collectors.toList());
- `map()`을 사용하면 각 문장이 단어 배열로 나뉜다 → Stream<Stream<String>>
- `"a b"` → `Stream.of("a", "b")`
- `"c d"` → `Stream.of("c", "d")`
// 출력결과
a
b
c
d
- `flatMap()`을 사용하면 모든 단어가 하나의 스트림으로 평탄화됨 → Stream<String>
// 출력결과
["a", "b", "c", "d"]
🔍 map() vs flatMap() 비교
항목 | `map()` | `flatMap()` |
목적 | 요소 변환 | 중첩된 요소를 펼침 |
결과 구조 | Stream<T> 또는 Stream<Stream<T>> | Stream<T> |
변환 수 | 1:1 변환 | 1:N 변환 + 평탄화 |
사용 예 | 문자열 대문자 변환, 수학 연산 | 리스트 안의 리스트 펼치기, 문장 → 단어 |
💡 언제 무엇을 써야 할까?
각 요소를 하나의 값으로 변환할 때는?
- `map()` 메소드 사용!
- 간단하게 변환할 수 있음(ex. 포맷 변경, 계산 등)
각 요소를 여러 값으로 변환 후 펼칠 때는?
- `flatMap()` 메소드 사용!
- 중첩된 구조를 해제할 수 있음(ex. 배열, 리스트)
✏️ 마무리
Java Stream API의 `map()`과 `flatMap()`은 개념이 비슷해 보이지만,
중첩 구조의 유무와 평탄화 여부에 따라 확연히 다르다!
“map()은 변환, flatMap()은 펼친다”
728x90