매핑
객체에서 특정 데이터를 선택하는 작업은 매우 흔한 일입니다. (SQL 특정 열 선택 등)
이번에는 이 특정 데이터를 선택하는 기능을 알아봅시다.
스트림의 각 요소에 함수 적용
map( )
'map( )'은 함수를 인수로 받으며, 그 결과는 새로운 요소로 매핑이 됩니다. (새로운 스트림이 만들어진다 생각하시면 편합니다.)
void mappingDishNameLength() {
List<Integer> dishNameLength = menu.stream() // Type : Stream<Dish>
.map(Dish::getName) // Type : Stream<String>
.map(String::length) // Type : Stream<Integer>
.collect(toList()); // Type : List<Integer>
System.out.println("메뉴명 길이 = " + dishNameLength);
}
스트림 평면화
이전에 배운 'distinct( )'를 이용해 고유 문자로 이루어진 리스트를 반환해 봅시다
문제가 발생했습니다. 'map( )'에서 사용한 'split( )'이 'String[ ]' 타입으로 반환하는 메서드입니다!
// Q: ["Hello", "World"] Ans: ["H", "e", "l", "o", "W", "r", "d"]
static void badDistinctWord() {
List<String[]> distinctList = StreamMapping
.distinctList.stream()
.map(word -> word.split("")) // Stream<String[]>
.distinct()
.collect(toList());
System.out.println("중복되지 않는 문자 = " + distinctList); // 결과 : "Hello", "World"
}
그래서 타입을 맞춘다 하더라도 'distinct( )'의 중복 검사는 String[ ] 배열 단위로 이루어지고, 결국 우리가 뜻하는대로 작동하지 않게 됩니다.
그래서 우리가 해야하는 것은 1차적으로 'String[ ]' 배열이 아닌 String 타입으로 분해를 해야 합니다.
그러기 위해서는 먼저 각 단어를 개별 문자열로 이루어진 배열로 만든 후 각 배열을 별도의 스트림으로 다시한번 만들어야 합니다!
2차시도
배열을 문자열로 한번 더 쪼개기 위해서는 stream을 두번 사용하면됩니다!
private static List<Stream<String>> flatMappingExampleV2(List<String> list) {
return list.stream()
.map(s -> s.split("")) // Stream<String[]>
.map(Arrays::stream) // Stream<Stream<String>>
.distinct()
.collect(toList());
}
여전히 문제가 있습니다.
'Arrays::stream'은 최종연산을 수행하지 않았기 때문에, 아직 Stream의 형태로 남아있습니다.
그래서 Stream<Stream<String>> 타입이 됩니다.
그래서 계층화된 Stream을 평면화할 필요가 있습니다. 이를 위해 'flatMap( )'이 필요합니다!
flatMap( )
flatMap( )은 말 그대로 Map을 Flat하게 계층화된 Stream<Stream<String>>을 Stream<String>으로 평면화시킬 수 있습니다.
private static List<Stream<String>> flatMappingExampleV2(List<String> list) {
return list.stream() // Stream<String>
.map(word -> word.split("")) // Stream<String[]>
.flatMap(Arrays::stream) // Stream<Stream<String>> -> Stream<String>
.distinct()
.collect(toList());
}
요약
map( )
- map()은 함수를 인수로 받으며, 그 결과들로 새로운 스트림을 만들어서 매핑.
flatMap( )
- 복합 스트림을 하나의 스트림으로 평면화 시켜서 새로운 스트림에 매핑.
- ex: Stream<Stream<String>> -> 새로운 Stream<String>
참고 자료
- 모던 자바 인 액션
- JAVA Reference
'JAVA > 모던 자바 인 액션' 카테고리의 다른 글
모던 자바 인 액션 10. 스트림 활용(4) - 리듀싱 (0) | 2021.08.18 |
---|---|
모던 자바 인 액션 09. 스트림 활용(3) (0) | 2021.08.18 |
모던 자바 인 액션 07. 스트림 활용(1) (0) | 2021.08.17 |
모던 자바 인 액션 06. 스트림 (0) | 2021.08.17 |
모던 자바 인 액션 05. 람다(4) (0) | 2021.08.16 |