[기본 개념] 9 | (2.2) 스트림 중간 연산

728x90

[기본 개념] 9 | (2.2) 스트림 중간 연산

1 스트림이란?

2 스트림 만들기

3> 스트림의 중간연산

4> Optional<T>와 OptionalInt

5 스트림의 최종연산

6 collect( )

7 Collector 구현하기

8 스트림의 변환

3. 스트림의 중간연산

스트림 자르기 - skip( ), limit( )

skip( )은 요소를 건너뛰고, limit( )는 요소의 개수를 제한한다.

 

IntStream intStream = IntStream.rangeClosed(1, 10) ;     // 1 ~ 10의 요소를 가진 스트림

intStream.skip(3).limit(5).forEach(System.out :: println) ;      // 45678

 

스트림의 요소 걸러내기 - filter( ), distinct( )

distinct( )는 스트림에서 중복된 요소들을 제거하고, filter( )은 주어진 조건에 맞지 않는 요소를 걸러낸다.

 

IntStream intStream = IntStream.of(1, 2, 2, 3, 3, 3, 4, 5, 5, 6) ;

intStream.distinct( ).forEach(System.out :: println) ;       // 123456

 

IntStream intStream = IntStream.rangeClosed(1, 10) ;  

intStream.filter(i -> i % 2 == 0).forEach(System.out :: println) ;       // 246810

 

정렬 - sorted( )

sorted( )는 지정된 Comparator로 스트림을 정렬하는 데, 대신 int값을 반환하는 람다식을 사용해도 된다. Comparator를 지정하지 않으면 스트림 요소의 기본 정렬 기준으로 정렬한다.

 

Stream<String> strStream = Stream.of("dd", "aaa", "CC", "cc", "b") ;

strStream.sorted( ).forEach(System.out :: println) ;    // CCaaabccdd

 

정렬에 사용되는 기본적인 메서드는 comparing( )이다. 비교대상이 기본형이면 comparing( )대신 comparingInt, comparingDouble, ComparingLong을 사용하여 오토박싱&언박싱과정을 줄여 효율적이게 하자. 

 

정렬조건을 추가할 때는 thenComparing( )을 사용한다.

 

예를 들어 학생 스트림을 반별, 성적순, 이름순으로 정렬하여 출력하려면 다음과 같이 한다.

 

studentStream.sorted(Comparator.comparing(Student :: getBan)

                                        .thenComparing(Student :: getTotalScore)

                                        .thenComparing(Student :: getName))

                                        .forEach(System.out :: println) ;

 

변환 - map( )

스트림의 요소에 저장된 값 중에서 원하는 필드만 뽑아내거나 특정 형태로 변환해야 할 때 map( )을 사용한다.

 

예를 들어 File의 스트림에서 파일의 이름(String)만 뽑아서 출력하고 싶을 때, 아래와 같이 map( )을 사용할 수 있다. 그리고 map( )도 중간 연산이고, filter( )처럼 하나의 스트림에 여러 번 적용할 수 있다.

 

fileStream.map(File :: getName)                                    // Stream<File> -> Stream<String>

       .filter(s -> s.indexOf('.') != -1)                                       // 확장자가 없는 것은 제외

       .map(s -> s.substring(s.indexOf('.') + 1))           // Stream<String> -> Stream<String>

       .map(String :: toUpperCase)                                    // 모두 대문자로 전환

       .distinct( )                                                                            // 중복 제거

       .forEach(System.out :: print) ;                                    // JAVATXT

 

조회 - peek( )

연산과 연산 사이에 올바르게 처리되었는지 확인하고 싶을 때 peek( )를 사용한다. 스트림의 요소를 소모하지 않으므로 여러 번 끼워넣어도 괜찮다.

 

fileStream.map(File :: getName)                                                              // Stream<File> -> Stream<String>

       .filter(s -> s.indexOf('.') != -1)                                                              // 확장자가 없는 것은 제외

       .peek(s -> System.out.printf("filename = %s%n", s))        // 파일명 출력

       .map(s -> s.substring(s.indexOf('.') + 1))                                         // 확장자만 추출

       .peek(s -> System.out.printf("extension = %s%n", s))       // 확장자를 출력

       .forEach(System.out :: print) ;

 

flatMap( ) - Stream<T[ ]>를 Stream<T>로 변환

스트림의 요소가 배열이거나 map( )의 연산결과가 배열인 경우, Stream<T>로 다루는 것이 편리할 때 map( )대신 flatMap( )을 사용하면 된다.

 

Stream<String[ ]> strArrStrm = Stream.of {

           new String[ ]{"abc", "def", "ghi"}, 

           new String[ ]{"ABC", "GHI", "JKLMN"}

} ;

Stream<String> strStrm = strArrStrm.flatMap(Arrays :: stream) ; 

 

이러면 각 요소의 문자열들을 합쳐서 문자열이 요소인 스트림 Stream<String>으로 만들 수 있다. 

 

 

 

 

 

 

출처 | Java의 정석 (남궁 성)

 

 

728x90