반응형

스트림의 중간연산

 


저번시간에는


skip() - 건너뛰기
limit() - 자르기,
dstinct() - 중복제거
filter() - 조건식에 맞지 않는 것을 제거
sorted() - 정렬

이러한 것들을 알아보았다.

 

이번시간에는 map(), peek(), flatmap() 에 대해서 알아볼 것이다.

map() - 스트림 요소 변환
peek() - forEach() 와 비슷한데,  forEach()는 최종연산이지만, peek()는 중간연산이다.
flatmap() - map과 거의 비슷한 변환이다.  스트림의 스트림을 -> 스트림으로 바꿔준다.  

자세히 알아보도록 하자.

 

  • 스트림 요소 변환하기 - map()

map() 메서드는 매개변수로 Function을 받는다. 
Function이란? 어떤 타입 T를 넣으면 그 결과로 R이 나오는 것이다. 
그래서 어떤 타입 Stream<T>가 Stream<R>로 바뀌는 것이다. 

이 코드는 map() 메서드를 이용해서 Stream<File>을 Stream<String>으로 바꾸는 것이다. 
File객체를 넣으면 getName()을 통해 이름을 얻는데 이때 이름은 문자열이다. 그것을 반환하는 것이다.

map(File::getName) 의 메서드 참조를 람다식으로 바꾸면,
map((f) ->f. getName()) 이렇게 바꿀 수 있다. 즉, file 객체를 주면, file객체에 getName()을 호출한 결과은 String을 반환하는 것이다.

그래서 map(File::getName) 메서드를 통해서  Stream<File> 을 Stream<String>으로 바꿀 수 있는 것이다. 

이것이 map() 메서드의 역할이다.

예를 들어서 파일 스트림(Stream<File)에서 파일 확장자(대문자를 중복없이 뽑아내고 싶으면, 
map()을 이용해서 Stream<File> -> Stream<String>  변환을 했다. 파일객체를 이름만 뽑아서 문자열 스트림을 만들었다.
filter()를 이용해서 확장자가 없는 것은 제외시켜주고,
map()을 이용해서 확장자를 뽑아냈다. 여기서는 같은 타입으로(<String> -> <String>) 변환을 했다. 즉 파일이름 전체 -> 파일 확장자만 반환하도록 하였다.
그리고 map()을 이용해서 대문자로 변환해주었다. 즉 소문자로 되어있는 것을 다 대문자로 변환해주었다.
distinct()로 중복을 제거하고,
forEach()로 출력했다. 그랬더니 확장자들을 출력할 수 있게되었다. 

 

 

  • 스트림의 요소를 소비하지 않고 엿보기 - peek()

peek는 forEach와 기능이 똑같다. peek가 forEach와 다른 점은,
forEach는 최종 연산 이라서 스트림을 소비하는 반면, peek는 중간 연산이라서 스트림을 소비 하지 않는 다는점이다.

즉, peek는 반환타입이 Stream이고, forEach는 반환타입이 void이다.

peek는 보통 어디에 사용하냐면,
fileStream을  변환할 때, 중간중간에 변환이 잘 되고 있는지 확인할 때 사용한다. 중간중간 디버깅 용도로 사용한다.

 

 

  • 스트림의 스트림을 스트림을 변환 - flatMap()

flatMap()은 스트림의 스트림을 스트림으로 변환할 때 사용한다.

예를 들어 위와 같은 문자열 배열 스트림이 있다. 즉, 스트림의 요소 하나가 String 배열이다.

이것을 만약 map을 이용해서 변환하면,
Stream<String[]>이 Stream<Stream<String>> 이렇게 바뀐다. 스트림의 스트림으로 바뀐다.

그런데, 사실은 내가 원했던 것은 Stream<String[]> 의 문자열 배열이 합쳐져서 Stream<String>이 되길 원했다.

문자열 배열들을 하나의 배열들로 합치고 싶은 것이다.
즉, 여러개의 문자열 배열들을 하나의 문자열 배열처럼 변환해서 Stream으로 만들고 싶은 것이다.

그런데 이때 그냥 map()을 사용하면 Stream<Stream<String>> 이렇게 스트림의 스트림이 되어버린다.

그래서 이럴 때는 map()이 아니라 flat(Map()을 사용해야 한다.

map(Arrays::stream)의 메서드 참조를 람다식으로 바꿔보면, (arr) -> Arrays.stream(arr) 어떤 배열을 주면 그것을 스트림으로 바꾸는 것이다. 그런데 map()으로 사용하면 스트림의 스트림이 된다.

그래서 아래의 결과처럼 각 문자열 배열의 요소가 하나의 스트림 요소로 들어오는 것을 원한다면, flatMap()을 사용해야 한다.

반응형

'JAVA' 카테고리의 다른 글

스트림의 최종연산  (0) 2022.11.25
Optional<T>  (0) 2022.11.22
스트림의 중간연산(1)  (0) 2022.11.19
스트림의 연산  (0) 2022.11.16
스트림 만들기  (0) 2022.11.15