685 단어
3 분
Java Stream - Map
2025-01-13

Map#

Stream API에서 map과 flatMap은 특정 데이터를 선택하는 기능을 한다.

Map#

map은 메서드를 파라미터로 받는다. 파라미터로 받은 메서드는 Stream 객체의 각 요소에 대해서 적용되어 메서드를 적용한 결과를 가진 새로운 Stream을 만들게 된다.


List<String> list = categories.stream() // Stream<Category>
    					.map(category -> category.getName()) // map(Category::getName), @return Stream<String>
    					.toList();
// 위의 예제에서 카테고리 이름의 길이를 알고 싶을 때
List<Integer> list = category.stream()
    						.map(Category::getName)
    						.map(String::length)
    						.toList();

위의 예제처럼 map은 여러개를 연결해, 계속해서 새로운 값으로 매핑할 수 있다. map(Category::getName)의 리턴 값은 Stream(String)이고, 이 객체에 대해서 다시 한번 map(String::length)로 매핑을 하면 Stream(Integer) 객체로 바뀐다.


Map에서 생길 수 있는 문제#

List<String> list = Arrays.asList("hello", "world");

만약 위의 코드에서 중복을 제거한 알파벳을 알고 싶다면 간단하게 아래와 같이 작성할 것이다.

list.stream()
    .map(str -> str.split(""))
    .distinct
    .toList();

그러나 map으로 전달한 람다식 str -> str.split("")은 String[]을 반환하고 따라서 리턴 값은 Stream<String[]>이다. 따라서 String[]에 대해서 중복을 제거하므로 출력은 아래와 같다.

[h, e, l, l, o]
[w, o, r, l, d]

그렇다면 매핑한 String[]에 대해서 하나의 스트림으로 만드는 방법은 어떨까? Arrays.stream()은 배열을 입력 받아 하나의 스트림으로 만드는 메서드이다.

String[] strArray = {"hello", "world"};

Stream<String> strStream = Arrays.stream(strArray); // String[] 배열의 String을 stream으로 바뀜

위의 방식을 이용해서 매핑해보자

list.stream()
    .map(str -> str.split(""))
    .map(Arrays::stream)
    .distinct()
    .toList();

이 코드는 제대로 동작할 것 같지만 그렇지 않다.

map(str -> str.split(""))Stream<String[]> 타입을 반환하고, map(Arrays.stream)Stream<String>을 반환한다. 이제 두 개의 연산을 이어서 수행하게 되면, Stream<Stream<String> 타입이 반환되어 원래의 의도와는 달라지게 된다.


flatMap#

위의 예제에서 잘못된 것을 flatMap을 이용하여 해결 할 수 있다.


map은 파라미터로 넘어온 람다식의 결과(String[]) 그 자체를 매핑하는 반면, flatMap의 경우 String[]의 내용물 로 매핑한다. 다시 말해서 여러 개로 나뉜 배열의 Stream하나의 Stream으로 바꾸는 것이다.

List<String> distinctList = list.stream()
    							.map(str -> str.split("")) // @return Stream<String[]>
    							.flatMap(word -> Arrays.stream(word)) // @return Stream<String>
    							//.flatMap(Arrays::stream)
    							.distinct()
    							.toList();

정리하자면 flatMapstream의 각 값을 다른 stream으로 매핑한 후 하나로 합치는 역할을 수행한다.


메서드반환 타입설명
mapStream<Stream>스트림으로 변환을 하지만 기존의 구조는 유지
flatMapStream중첩된 스트림을 하나의 스트림으로 변환
Java Stream - Map
https://realits.me/posts/java-stream-map/
저자
realitsyourman
게시일
2025-01-13
라이선스
CC BY-NC-SA 4.0