언어(Language)/Java

[Java] 자바 스트림 파이프라인 개념 정리 및 활용

잇트루 2022. 9. 26. 02:00
반응형

리덕션(Reduction)

대량의 데이터를 가공하여 축소하는 것을 리덕션이라 한다.

데이터의 합계, 평균값, 카운팅 등 연산의 결괏값을 나타내는 것이 리덕션의 결과물이라 할 수 있다.

그러나, 컬렉션의 요소를 리덕션의 결과물로 바로 집계할 수 없을 때에는 필터, 매핑, 정렬, 그룹화와 같은 중간 연산이 필요하다.

 

파이프라인(Pipelines)

리덕션의 결과물을 위해 중간 연산과 최종 연산을 수행하도록 하기 위해 파이프라인을 사용한다.

파이프라인은 여러 개의 스트림이 연결되어 있는 것을 뜻한다. 연결된 스트림에서 최종 연산을 제외하고는 모두 중간 연산 스트림이다.

중간 스트림이 생성될 때 요소들이 바로 중간 연산이 되는 것은 아니다.

최종 연산이 시작되기 전까지는 지연되며, 최종 연산이 시작되는 시점부터 컬렉션의 요소가 하나씩 중간 스트림에서 연산되고 최종 연산까지 오게 되는 구조이다.

 

Stream 인터페이스에는 필터링, 매핑, 정렬 등의 다양한 중간 연산 메서드를 제공한다.

이 메서드들은 중간 연산된 스트림을 리턴하고, 이를 다시 중간 연산 메서드를 호출하여 파이프라인을 형성한다.

 

파이프라인 예제

만약, 다음과 같이 회원 컬렉션에서 남자 회원의 평균 나이를 구하는 상황이 있다고 가정한다.

  1. 회원 컬렉션에는 남성과 여성회원이 함께 존재한다.
  2. 남자만 필터링하는 중간 스트림을 연결한다.
  3. 이를 다시 나이로 매핑하는 중간 스트림을 연결한다.
  4. 최종 연산을 통해 남자 회원의 평균 나이를 집계한다.

파이프라인을 사용하지 않는 코드로 표현하면 다음과 같다.

// 오리지널 스트림
// 회원 컬렉션의 회원 스트림 생성
Stream<Member> memberStream = list.stream();

// 중간 연산
// 회원 스트림을 필터링하여 남자 회원을 생성하는 새로운 스트림 생성
Stream<Member> maleStream = memberStream.filter(m -> m.getGender() == Member.MALE);

// 중간 연산
// 남자 회원 스트림 객체를 나이와 매핑하여 age를 요소로 하는 새로운 스트림 생성
IntStream maleAgeStream = maleStream.mapToInt(Member::getAge);

// 최종 연산
// average() 메서드를 활용하여 age의 평균을 저장
OptionalDouble opd = maleAgeStream.average();

// getAsDouble() 메서드를 호출하여 남자 회원의 평균 나이를 저장
double maleAgeAverage = opd.getAsDouble();

이를 파이프라인으로 연결하여 다음과 같이 코드를 작성할 수 있다.

double maleAgeAverage = list.stream() // 스트림 생성(오리지널 스트림)
    .filter(m -> m.getGender() == Member.MALE) // 중간 연산
    .mapToInt(Member::getAge) // 중간 연산
    .average() // 최종 연산
    .getAsDouble();
반응형