숫자형 스트림

반응형
728x90
반응형

숫자형 스트림

reduce 메서드를 사용하여 스트림 요소의 합을 구하는 예제를 보자.

int calories = menu.stream()
                  .map(Dish::getCalories)
                  .reduce(0, Integer::sum);

 

위 코드에는 박싱이 숨어져있는데, 내부적으로 합계를 계산하기 전에 Integer를 기본형(int)로 언박싱 해야한다.

int calories = menu.stream()
                  .map(Dish::getCalories)
                  .sum(); // 호출 불가능

 

직접 sum 메서드를 호출한다면 훨씬 좋겠지만, 위 코드처럼 sum 메서드를 직접 호출할 수 없다. map 메서드가 Stream를 생성하기 때문이다. 이를 해결하기 위해서 스트림은 API 숫자 스트림을 효율적으로 처리할 수 있도록 기본형 특화 스트림을 제공한다.

 

 

 

기본형 특화 스트림

자바 8에서 제공되는 기본형 특화 스트림은 3가지이다.

1) int 요소 : IntStream
2) double 요소 : DoubleStream
3) long 요소 : LongStream

 

각각의 인터페이스는 숫자 스트림의 합계를 계산하는 sum, 최댓값 요소를 검색하는 max 같이 자주 사용하는 숫자 관련 리듀싱 연산 수행 메서드를 제공한다. 또한 필요할때 다시 객체 스트림으로 복원하는 기능도 제공한다.

 

 

 

숫자 스트림으로 매핑

스트림을 특화 스트림으로 변환할 때에는 mapToInt, mapToDouble, mapToLong 3가지 메서드를 가장 많이 사용한다.

int calories = menu.stream()
                  .mapToInt(Dish::getCalories)
                  .sum();

 

mapToInt 메서드는 각 요리에서 모든 칼로리(Integer 형식)를 추출한 다음에 IntStream을 반환한다. 따라서 IntStream 인터페이스에서 제공하는 sum 메서드를 이용해서 칼로리 합계를 구할 수 있다. 스트림이 비어있으면 sum 메서드의 반환 값은 0이다.

 

 

객체 스트림으로 복원

숫자 스트림을 만든 다음에 원상태인 특화되지 않은 스트림으로 복원해보자.

IntStream intStream = menu.stream().mapToInt(Dish::getCalories); // 스트림을 숫자 스트림으로 변환
Stream<Integer> stream = intStream.boxed(); // 숫자 스트림을 스트림으로 변환

 

위 예제는 boxed 메서드를 이용해서 특화 스트림을 일반 스트림으로 변환하고 있다. IntStream의 map 연산은 int 인수로 받아서 int를 반환하는 람다를 인수로 받는데, 정수가 아닌 Dish 같은 다른 값들을 반환하기 위해서 스트림 인터페이스에 정의된 일반적인 연산을 사용하고있다.

 

 

기본값 OptionalInt

합계 예제에서 0이라는 기본값이 있을때에는 별 문제가 없었는데, IntStream에서 최댓값을 찾을 때는 0이라는 기본값 때문에 잘못된 결과가 나올 수 있다. 스트림에 요소가 없을때와 실제로 최대값이 0인 상황을 구별해야한다. OptionalInt를 이용해서 IntStream의 최댓값 요소를 찾을 수 있다.

OptionalInt maxCalories = menu.stream()
                              .mapToInt(Dish::getCalories)
                              .max();

 

OptionalInt를 이용해서 최대값이 없는 상황에 사용할 기본값을 명시적으로 정의할 수 있다.

int max = maxCalories.orElse(1);

 

 

숫자 범위

프로그램에서는 특정 범위의 숫자를 이용해야하는 상황이 자주 발생한다. 예시로, 1~100 사이의 숫자를 생성하려고 할때 IntStream, LongStream에서는 range와 rangeClosed라는 두가지 정적 메서드를 제공한다. 두 메서드 모두 첫번째 인수로 시작 값을, 두번째 인수로 종료값을 갖는다.

 

1) range 메서드 : 시작값과 종료값이 결과에 포함되지 않는다.
2) rangeClosed 메서드 : 시작값과 종료값이 결과에 포함된다.

 

IntStream evenNumbers = IntStream.rangeCLosed(1, 100)
                                .filter(n -> n % 2 == 0);

 

반응형

'Coding > Java' 카테고리의 다른 글

의존 객체 주입의 사용 이유  (0) 2020.11.06
제네릭 메서드  (0) 2020.11.06
싱글턴 패턴  (0) 2020.11.06
스트림 연산  (0) 2020.11.06
스트림 vs 컬렉션  (0) 2020.11.06

Designed by JB FACTORY