자바/스트림

스트림의 중간 연산(2)

백_곰 2022. 4. 14. 10:59

1. 변환 - map()

- 스트림의 요소에 저장된 값 중에서 원하는 필드만 뽑아내거나 특정 형태로 변환해야

할 때가 있다. 이 때 사용하는 것이 아래와 같은 map() 메서드이다.

 

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

 

 

 

- 아래의 예제를 통해 이해하자.

 

Stream<File> fileStream = Stream.of(new File("Ex1.java"), new File("Ex2.java"));

// 해당 파일들의 명을 가져온다.

 

Stream<String> filenameStream = fileStream.map(File::getName);

// map()을 통해 Stream<File> -> Stream<String>으로 변환함.

 

 

 

- 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);                 

 

 

 

 

 

1-1. 변환 - map()을 이해하기 위한 예제(1)

 

 

 

 

1-2. mapToInt(), mapToLong(), mapToDouble()

- map() 연산은 Stream<T> 타입의 스트림 결과를 가져오는데, 만약 숫자나, 소수점이 결과로 나온다면,

map() 뒤에 결과의 타입에 맞는 것을 써 주는 것이 효율적이다.

 

 

- 아래의 코드를 보고 이해하자.

 

스트림의 중간 연산(1) (tistory.com)

 

스트림의 중간 연산(1)

1. 스트림 자르기 - skip(), limit() - skip() 메서드는 지정한 매개변수만큼 스트림의 요소를 건너뛴다. - limit() 메서드는 지정한 매개변수만큼 스트림의 요소를 제한한다. - 기본형 Stream에서도 정의되

kind-coding.tistory.com

예제 3-1에서 했던 studentStream에서 스트림에 포함된 모든 성적을 합산해야 한다면, map() 메서드를

통해 총점을 뽑을 수 있다.

 

Stream<Integer> studentScoreStream = studentStream.map(Student::getTotalScore)

 

( 그러나, 이렇게 성적이 int로 예측이 가능한 것은 mapToInt()를 사용해서 IntStream의 타입을

이용하는 것이 효율적이다. )

 

IntStream studentScoreStream = studentStream.mapToInt(Student::getTotalScore);

int allTotalScore = studentScoreStream.sum();

 

( count()만 지원하는 Stream<T>와 달리 기본형 스트림을 쓰게 된다면, sum() 뿐만 아니라,

average(), max(), min()도 쓸 수 있다. )

( 위 메서드들은 최종 연산이므로, 스트림을 또 하나 만들어주어야 한다. )

( 그러므로, sum()average()를 둘 다 쓸 경우가 있을 때 다시 만들어주어야 한다는 불편함이 있다.)

( 그래서 summaryStatistics()라는 메서드가 제공해준다. )

( 사용방법은 아래와 같다. )

 

IntSummaryStatistics stat = ScoreStream.summaryStatistics();

long totalCount = stat.getCount();

long totalScore = stat.getSum();

double avgScore = stat.getAverage();

 

( 추가적으로 LongStream, DoubleStream에게도 지원한다. )

 

( 또한 반대로 IntStreamStream<T>로 변환할 때는 mapToObj()를 쓴다. )

( 그리고 IntStreamStream<Integer>로 변환할 때는 boxed()를 쓴다. )

 

 

 

 

1-3. 변환 - map()을 이해하기 위한 예제(2)

: 로또 번호를 생성해서 출력하는 코드인데, mapToObj()를 이용해서 IntStreamStream<String>

으로 변환하는 예제이다.

 

 

 

 

 

1-4. 변환 - map()을 이해하기 위한 예제(3) 

: CharSequence에 정의된 chars()는 String이나 StringBuffer에 저장된 문자들을 IntStream

으로 다룰 수 있게 하는 예제이다.

 

 

 

 

 

2. 조회 - 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))    // Stream<String> -> Stream<String>

.peek(s -> System.out.printf("extension = %s\n", s)

.distinct()                                        // 중복 제거

.forEach(System.out::print);