mapToInt( ), mapToLong( ), mapToDouble( )

Stream<T>타입의 스트림을 기본형 스트림으로 변환할때 아래의 메서드들을 사용한다.

DoubleStream	mapToDouble(ToDoubleFunction<? super T> mapper)
IntStream		mapToInt(ToIntFunction<? super T> mapper)
LongStream		mapToLong(ToLongFunction<? super T> mapper)

스트림에 포함된 모든 학생의 성적을 합산해야 하는 경우가 있다고 가정하면,
두 가지 방법이 있을 수 있다.

  • map( )으로 학생의 총점을 뽑아서 새로운 스트림을 반환받기
Stream<Integer> studentScoreStream = studentStream.map(Student::getTotalScore);
  • mapToInt( )를 사용하여 기본형 스트림을 반환받기
IntStream studentScoreStream = studentStream.mapToInt(Student::getTotalScore);
int allTotalScore = studentScoreStream.sum(); // int sum();

💡 위와 같은 경우, 성적을 더할 때 Integer를 int로 변환하지 않는, mapToInt( )를 사용하는 것이 더 효율적이다.

IntStream의 메서드

  • count( )만 지원하는 Stream<T>와 다르게 기본형 스트림은 숫자를 다루는데 편리한 메서드들을 제공한다.
int						sum()		// 스트림의 모든 요소의 총합
OptionalDouble			average()	// sum() / (double)count()
OptionalInt 			max()		// 스트림의 요소 중 제일 큰 값
OptionalInt				min()		// 스트림의 요소 중 제일 작은 값

💡 위 메서드들은 최종연산이기 때문에 호출 후에 스트림이 닫힌다는 점에 주의하자

// Stream의 최종 연산 예제
IntStream scoreStream = studentStream.mapToInt(Student::getTotalScore);

long totalScore = scoreStream.sum(); // sum()은 최종연산 이므로 호출 후 스트림이 닫힘
OptionalDouble average = scoreStream.average(); // 에러. 스트림이 이미 닫혔음

double d = average.getAsDouble(); // OptionalDouble에 저장된 값을 꺼내서 d에 저장

IntSummaryStatistics

  • sum( )과 average( )를 모두 호출해야 할 때, 스트림이 이미 닫혔기 때문에 다시 생성해야 하는 불편함을 해결하기 위해 summaryStatistics( ) 메서드가 제공된다.
// IntSummaryStatistics 반환 받기
IntSummaryStatistics stat = scoreStream.summaryStatistics();

IntSummaryStatistics는 다음과 같은 메서드들을 제공한다.

  • getCount( ) - 개수를 반환
  • getSum( ) - 합계를 반환
  • getAverage( ) - 평균을 반환
  • getMin( ) - 최소 값을 반환
  • getMax( ) - 최대 값을 반환

Stream의 변환

  • IntStream -> Stream<T>
Stream<U>		mapToObj(IntFunction<? extends U> mapper)
  • IntStream -> Stream<Integer>
Stream<Integer>	boxed()
// 로또번호 생성해서 출력하는 예제(mapToObj() 사용)
IntStream intStream = new Random.ints(1,46); // 1~ 45사이의 정수(46은 포함 안됨)
Stream<String> lottoStream = intStream.distinct().limit(6).sorted().
							mapToObj(i -> i + ","); // 정수를 문자열로 반환

lottoStream.forEach(System.out::print); // 12,14,20,23,26,29,(출력시 마다 결과가 바뀔 수 있음)
                                    

CharSequence

  • CharSequence에 정의된 chars( )는 String이나 StringBuffer에 저장된 문자들을 IntStream으로 다룰 수 있게 해준다.
IntStream charStream = "12345".chars();  	// default IntStream chars()
int		  charSum 	 = charStream.map(ch -> ch - '0').sum(); // charSum = 15

IntStream으로의 변환

  • Stream<String> -> IntStream
    mapToInt(Integer::parseInt)를 사용한다.
  • Stream<Integer> -> IntStream
    mapToInt(Integer::intValue)를 사용한다.

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

// Stream<String[]> -> map(Arrays::stream)으로 변환하는 예제
Stream<Stream<String>> strStrStrm = strArrStrm.map(Arrays::stream);

💡 Stream<String[ ]>을 map( )을 사용하여 변환하면 Stream<Stream>이 반환된다.

  • 즉 스트림 안의 스트림인 것이다.

  • 스트림 안의 스트림이 되지 않도록 하려면 flatMap( )을 사용하면 된다.

  // map()을 사용할때의 예제
Stream<Stream<String>> strStrStrm = strArrStrm.map(Arrays::stream);
  
  // flatMap()을 사용할때의 예제
Stream<String> strStrm = strArrStrm.flatMap(Arrays::stream);
  • 스트림을 하나의 스트림으로 합칠때도 flatMap( )을 사용한다.
// Stream 합치기 예제
Stream<String> strStrm = Stream.of("abc", "def", "jklmn");
Stream<String> strStrm2 = Stream.of("ABC", "GHI", "JKLMN");
  
Stream<Stream<String>> strmStrm = Stream.of(strStrm, strStrm2);
  
Stream<String> strStream = strmStrm
  .map(s -> s.toArray(String[]::new) // Stream<Stream<String>> -> Stream<String[]>
  .flatMap(Arrays::stream);

위의 예제는 Stream<String>으로 변환하려면 위와 같이 map( )과 flatMap( )을 함께 사용해야 한다.

Optional<T>와 OptionalInt

  • 최종 연산의 결과 타입이 Optional인 경우가 있다.
  • Optional<T>은 지네릭 클래스로, T타입의 객체를 감싸는 래퍼 클래스이다.
  • Optional타입의 객체에는 모든 타입의 참조변수를 담을 수 있다.
// Optional의 정의
public final class Optional<T> {
  	private final T value; 	// T타입의 참조변수
  	...
  }

Optional의 사용이유

  • 최종 연산의 결과를 그냥 반환하지 않고, Optional객체에 담아서 반환한다.
  • 반환된 결과가 null인지 매번 if문으로 체크하는 대신 Optional에 정의된 메서드를 활용하여 간단히 처리가 가능하다.

Optional객체를 생성할 때는 of( ) 또는 ofNullable( )을 사용한다.

  • 참조변수의 값이 null일 가능성이 있으면, ofNullable( )을 사용해야한다.
  • of( )는 매개변수의 값이 null이면 NullPointerException이 발생하기 때문이다.
Optional<String> optVal = Optional.of(null); // NullPointerException 발생
Optional<String> optVal = Optional.ofNullable(null); // OK
  • Optional<T> 타입의 참조변수를 기본값으로 초기화할 때는 empty( )를 사용
  • null로 초기화 하는 것보다 empty( )사용이 권장된다.
Optional<String> optVal = null;  // 널로 초기화
Optional<String> optVal = Optional.<String>empty(); // 빈 객체로 초기화

💡 empty( )는 지네릭 메서드라서 앞에를 붙였다. 추정 가능하므로 생략할 수 있다.

출처 : 자바의 정석 3rd Edition(남궁성 저, 도우출판)

0개의 댓글