DEV-STUDY/Java

[Java] Stream - map과 flatmap 비교

HwangJerry 2023. 7. 4. 12:53
출처: https://devjem.tistory.com/41

 

최근 스트림 API에 대해 집중적으로 공부하는 와중에 map과 flatMap의 차이점을 더 자세히 정리하고 싶어서 포스팅을 하게 되었습니다.

 

 

Map이란?


map은 스트림 내부의 요소 하나하나에 접근해서 제가 파라미터로 넣어준 함수를 실행한 뒤 최종연산에서 지정한 형식으로 반환해주는 메서드 입니다. 

 

   List<Person> people = Arrays.asList(
                new Person("personA", 24),
                new Person("personB", 26),
                new Person("personC", 28),
                new Person("personD", 30)
        );

 

위와 같은 리스트를 예시로 만들어보겠습니다. 

 

List<String> nameList = people.stream()
                .map(person -> person.getName())
                .collect(Collectors.toList());

map 메서드 내부를 보면 람다 표현식이 인자로 들어간 것을 알 수 있습니다. 

 

람다 표현식은

 

1. people 리스트의 Person 객체 하나하나에 접근한다.

2. getName 메서드를 통해 name값을 얻는다. 

3. name값들을 포함하는 list를 최종적으로 만들어서 반환한다.

 

라는 과정을 나타냅니다. 

 

스트림을 쓰지 않을때는 for문을 사용해서 요소 하나하나에 접근해야 했지만, map이 반복문의 역할을 대신해주는 것입니다. 

 

nameList = [personA, personB, personC, personD]

 

결과를 출력했을때 정상적으로 name값들로 만들어진 리스트가 반환된 것을 알 수 있습니다. 

 

 

 

flatMap이란?


map에 대해서는 간략하게 알아봤는데, flatMap은 어떤 기능을 가지고 있을까요? 

 

flatMap은 스트림 평면화라는 이름으로도 불립니다. flatMap은 예시를 먼저 보는것이 이해하기 쉽기 때문에 아래의 코드를 한번 보겠습니다. 

 

animal = ["cat","dog"] 

 

위의 리스트에 스트림을 적용하여 cat과 dog의 철자 하나하나를 분리해서 새로운 리스트로 만드는 작업을 진행해보겠습니다.

 

원하는 결과  = [ "c", "a", "t", "d", "o", "g" ]

 

먼저 map을 사용해서 철자들을 분리해보겠습니다. 

 

List<String[]> results = animals.stream().map(animal -> animal.split(""))
                                .collect(Collectors.toList());

 

분명 split 메서드를 이용하여 철자를 모두 분리했는데 반환값 타입을 보면 List<String[]>이 나온것을 알 수 있습니다.

 

[  [  "c", "a", "t"  ] , [ "d", "o", "g" ]  ]    

 

즉, 위의 그림과 같이 animals 리스트 내부에서 각각의 요소별로 리스트을 중복으로 만들었다고 할 수 있습니다. 

 

우리가 원하는 것은 리스트가 중복되는 것이 아니라 하나의 스트림에 철자 하나하나가 다 들어가는 것입니다. 

 

이때 사용되는것이 flatMap, 다시 말해 중복된 스트림을 1차원으로 평면화 시키는 메서드입니다. 

 

List<String> results = animals.stream().map(animal -> animal.split(""))
        .flatMap(Arrays::stream)
        .collect(Collectors.toList());

 

여기서 flatMap 내부의 Arrays::stream은 배열을 스트림으로 변환해주는 메서드 참조 표현입니다. 

 

flatMap을 사용하면 각각의 String 리스트를 스트림으로 만드는 것이 아니라, String 리스트를 감싸고 있는 더 큰 스트림의 컨텐츠, 즉 구성 요소로 만들어 줄 수 있습니다. 

 

results = [c, a, t, d, o, g]

 

이처럼 flatMap을 사용하면 중복 구조로 되어있는 리스트를 하나의 스트림처럼 다룰 수 있습니다.