[ODOP:09][분석 실패] 박싱 스트림이 어떤 성능 저하를 일으킬까?

Stream 에서 박싱 스트림이 성능적으로 안좋다고 하는데 어떤 경우에 성능이 떨어지는지 분석하는 내용 입니다 결과적으로 어떻게 코드를 작성 해야 성능이 낮아지는지 알지 못했습니다.

Stream 에서 박싱 스트림이 성능적으로 안좋다고 하는데 어떤 경우에 성능이 떨어지는지 분석하는 내용 입니다
결과적으로 어떻게 코드를 작성 해야 성능이 낮아지는지 알지 못했습니다.

Stream<Integer> 를 사용하여 데이터를 처리한다고 가정 해 보자

Stream<Integer> intStream = Stream.of(1, 2, 3, 4, 5);  
intStream  
    .map(n -> n * 2)  
    .forEach(System.out::println);

위 코드 에서 map 연산은 각 숫자를 2배로 만드는 작업을 한다

이 과정에서 n + 2 의 결과는 초기 Stream 생성 시 아래의 코드를 통해 생성 되었다

public interface Stream<T> extends BaseStream<T, Stream<T>> {

	...

	public static<T> Stream<T> of(T... values) {  
	    return Arrays.stream(values);  
	}

	...
}	

오토 박싱이 일어나는 경우는, 기본 타입을 직접적으로 다룰 때 이다

우리가 위에서 Stream.of 로 생성 한 Stream 객체는, 제네릭으로 만들어 져 있고 제네릭은 primitive 타입을 허용하지 않는다
또한, Stream 을 선언 할 때 Integer 가 제네릭으로 들어가는 모습을 볼 수 있다
해당 Stream 이 생성 되는 시점에서 이미 래핑을 진행 하므로 지속적인 형변환은 일어나지 않는다

이해못함...

아래의 예시를 보자

int[] numbers = {1, 2, 3, 4, 5};
Stream.of(numbers)
      .map(n -> n[0] * 2)
      .forEach(System.out::println);

이 예시는 primitive 타입을 그대로 사용하고 있는 것을 볼 수 있다

래퍼타입의 지속적인 생성으로 인한 오버헤드가 문제가 되는 주요 상황은

Stream 이 기본 타입을 직접 다룰 때 발생한다

Stream API 는 기본적으로 각 함수에서 불변성을 유지한다

즉, 원본 데이터는 변경되지 않으며 각 중간 연산 마다 새로운 Stream 을 반환한다

이 과정에서 Wrapper 타입이 아니라 primitive 타입을 사용하며 해당 스트림을 Stream<int[]> 에서 Stream<Integer> 로 변환하는 경우에 책에서 말하는 오버헤드가 발생할 가능성이 있다

하지만 위 코드는 사실 극단적으로 Stream 을 억까 하려는 듯한 코드 이다

저런 경우가 흔히 생기지도 않으며 킹갓제네럴엠페러자바센세는 모든것을 계획 해 두셨다

만약 int[ ] 를 Stream 으로 쓰고싶으면

아주 간단한 해결 방식을 제공한다

int[] numbers = {1, 2, 3, 4, 5};
Arrays.stream(numbers)  // IntStream 생성
      .map(n -> n * 2)  // 각 요소를 2배로 만듦
      .forEach(System.out::println);  // 결과 출력

위와 같이 작성하는 경우 numbers 는 IntStream 이 된다