맨땅에 헤딩하는 개바른자

[Java] Stream > flatMap 본문

JAVA/Stream

[Java] Stream > flatMap

앵낄낄 2023. 6. 8. 20:13
반응형

git

https://github.com/ymwoo88/stream/tree/feature/flatMap-%EC%98%88%EC%A0%9C

설명

Stream 안에 있는 데이터 자체도 Stream일 경우
즉, Stream 안에 Stream(중첩)된 경우 이것을 하나의 Stream으로 풀어서 반환해주는 기능을 제공합니다.

Map과 유사한 기능을 제공하지만 다른 부분은 Stream<Stream> 형태가 된 것을 Flat이 하나의 Stream으로(Stream) 만들어 반환해준다고 생각하면 됩니다.

flatMap

이 스트림의 각 요소를 제공된 매핑 함수를 각 요소에 적용하여 생성된 매핑된 스트림의 내용으로 대체한 결과로 구성된 스트림을 반환합니다. 콘텐츠가 이 스트림에 배치된 후 각 매핑된 스트림이 닫힙니다. (매핑된 스트림이 null이면 빈 스트림이 대신 사용됩니다.)
이것은 중간 작업입니다.
매개변수:
mapper – 새로운 값의 스트림을 생성하는 각 요소에 적용되는 비간섭, 상태 비저장 함수
보고:
새로운 스트림
API 참고:
flatMap() 작업은 스트림의 요소에 일대다 변환을 적용한 다음 결과 요소를 새 스트림으로 평면화하는 효과가 있습니다.
예.
주문이 구매 주문의 스트림이고 각 구매 주문에 라인 항목 모음이 포함된 경우 다음은 모든 주문의 모든 라인 항목을 포함하는 스트림을 생성합니다.
  orders.flatMap(주문 -> order.getLineItems().stream())...
path가 파일의 경로인 경우 다음은 해당 파일에 포함된 단어의 스트림을 생성합니다.
  Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8); Stream<String> words = lines.flatMap(line -> Stream.of(line.split(" +")));
flatMap에 전달된 매퍼 함수는 간단한 정규식을 사용하여 줄을 단어 배열로 분할한 다음 해당 배열에서 단어 스트림을 만듭니다.
또한보십시오:
mapMulti

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

예제

  • 샘플 데이터
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
    private Long id;
    private String name;
    private String email;
    private Integer age;
    private Boolean isWorking;
    private List<String> hobbies;


    public static User getUserAmil() {
        return User.builder()
                .id(1L)
                .name("amil")
                .email("amil@ymwoo.com")
                .age(28)
                .isWorking(true)
                .hobbies(List.of("골프", "영화감상"))
                .build();
    }

    public static User getUserBenny() {
        return User.builder()
                .id(2L)
                .name("benny")
                .email("benny@ymwoo.com")
                .age(26)
                .isWorking(true)
                .hobbies(List.of("골프", "낚시"))
                .build();
    }

    public static User getUserCho() {
        return User.builder()
                .id(3L)
                .name("cho")
                .email("cho@ymwoo.com")
                .age(33)
                .isWorking(false)
                .hobbies(List.of("등산", "캥핌"))
                .build();
    }

    public static List<User> getExamUserList() {
        return Arrays.asList(getUserAmil(), getUserCho(), getUserBenny());
    }
}
  • 예졔1) 유저목록에서 취미목록을 추출
@Test
@DisplayName("유저목록에서 취미목록을 추출")
void case1() {
    List<User> examUserList = User.getExamUserList();

    // 좋지 않은 예시
    List<List<String>> badHobbies = examUserList
            .stream()
            .map(User::getHobbies)
            .toList();
    List<String> badHobbiesSimpleList = new ArrayList<>();
    for (List<String> secondStream : badHobbies) { // List<List<>> 이중 List를 벗기기위해 2번의 for문이 필요하다
        for (String hobby : secondStream) {
            badHobbiesSimpleList.add(hobby);
        }
    }
    badHobbiesSimpleList.forEach(s -> log.info("[bad] Hobbies info : {}", s));

    // 좋은 예시
    List<String> goodHobbies = examUserList
            .stream()
            .map(User::getHobbies)
            .flatMap(secondStream -> secondStream.stream()) // 상위 첫 stream 흐름에서 두번 째 secondStream을 열었다 Stream<Stream<>> 이런 형태이다
            // 위 상황이 Stream<Stream<>> 이런 형태이다 여기서 flatMap으로 Stream<>형태로 짜부시켜 준것이다.
            .toList();
    goodHobbies.forEach(s -> log.info("[good] Hobbies info : {}", s));
}
19:58:09.810 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [bad] Hobbies info : 골프
19:58:09.813 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [bad] Hobbies info : 영화감상
19:58:09.813 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [bad] Hobbies info : 등산
19:58:09.813 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [bad] Hobbies info : 캥핌
19:58:09.813 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [bad] Hobbies info : 골프
19:58:09.813 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [bad] Hobbies info : 낚시

19:58:09.814 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [good] Hobbies info : 골프
19:58:09.814 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [good] Hobbies info : 영화감상
19:58:09.814 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [good] Hobbies info : 등산
19:58:09.814 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [good] Hobbies info : 캥핌
19:58:09.814 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [good] Hobbies info : 골프
19:58:09.814 [Test worker] INFO com.ymwoo.stream.flatmap.StreamFlatMapTest -- [good] Hobbies info : 낚시

bad와 good의 결과는 동일하다

참조

https://backtony.github.io/java/2022-02-06-java-46/

반응형

'JAVA > Stream' 카테고리의 다른 글

[Java] Stream > foreach  (0) 2023.06.20
[Java] Stream > distinct  (0) 2023.06.08
[Java] Stream > map  (0) 2023.06.08
[Java] Stream > sorted  (0) 2023.05.31
[Java] Stream > Filter  (0) 2023.05.31