ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java - 스트림(Stream) 파이프라인
    Language/Java 2022. 11. 30. 16:45

    스트림(Stream) 파이프라인

    스트림 파이프라인

    스트림은 데이터의 필터링, 매핑, 정렬, 그룹핑 등의 중간 처리와 합계, 평균, 카운팅, 최댓값, 최솟값 등의 최종 파이프라인으로 해결한다. 여기서, 파이프라인은 컴퓨터 과학에서 한 데이터 처리 단계의 출력이 다음 단계의 입력으로 이어지는 형태로 연결된 구조를 말한다. 최종 처리 스트림과 오리지널 스트림을 제외한 나머지 스트림은 중간 처리 스트림으로 볼 수 있다.

     

     

    위의 그림을 보면 알 수 있듯이, 이전 데이터 처리의 출력이 다음 단계의 입력으로 이어진다. 좀 더 구체적으로 말하자면, 스트림 인터페이스에는 필터링, 매핑, 정렬 등의 많은 중간 처리 메서드가 있는데, 이 메서드들은 중간 처리된 스트림을 반환한다. 그리고 이 스트림에서 다시 중간 처리 메서드를 호출해서 파이프라인을 형성하게 된다.

     

    스트림 파이프라인에는 한 가지 중요한 특징이 존재한다. 바로 지연(lazy)인데, 중간 스트림이 생성될 때 요소들이 바로 중간 처리되는 것이 아니라 최종 처리가 시작되기 전까지 중간 처리는 지연이 된다. 즉, 최종 처리가 시작이 되어야 비로소 컬렉션의 요소가 하나씩 중간 스트림에서 처리가 되고 최종 처리까지 오게 되는 것이다.

     

     

    위 그림은 회원 컬렉션에서 남자만 필터링하는 중간 스트림을 연결하고, 다시 남자의 나이로 매핑하는 스트림을 연결한 후, 최종적으로 남자의 평균 나이를 집계하는 파이프라인을 나타낸 것이다.

     

    public class Main {
        public static void main(String[] args) {
            List<Member> members = Arrays.asList(
                    new Member("홍길동", Gender.MALE, 30),
                    new Member("임꺽정", Gender.MALE, 22),
                    new Member("이순신", Gender.MALE, 25),
                    new Member("이강인", Gender.FEMALE, 29)
            );
    
            Stream<Member> memberStream = members.stream();
            Stream<Member> maleMemberStream = memberStream.filter(member -> member.getGender().equals(Gender.MALE));
            IntStream ageStream = maleMemberStream.mapToInt(member -> member.getAge());
            OptionalDouble optionalDouble = ageStream.average();
            double ageAvg = optionalDouble.getAsDouble();
    
            System.out.println(ageAvg);
        }
    }

    위 과정을 소스코드로 작성해 보았다. 코드를 이해할 필요는 없고, 이것이 가장 원초적인 스트림 파이프라인의 코드라는 정도만 알고 넘어가면 된다.

    지역 변수를 하나하나 정의하였고, 그다음 지역 변수를 정의할 때 이전에 사용한 지역 변수에서 메서드를 호출하는 방식으로 사용하였다. 위에서 설명한 것과 일치한다.

     

    public class Main {
        public static void main(String[] args) {
            List<Member> members = Arrays.asList(
                    new Member("홍길동", Gender.MALE, 30),
                    new Member("임꺽정", Gender.MALE, 22),
                    new Member("이순신", Gender.MALE, 25),
                    new Member("이강인", Gender.FEMALE, 29)
            );
    
            double ageAvg = members.stream()
                            .filter(member -> member.getGender().equals(Gender.MALE))
                            .mapToInt(member -> member.getAge())
                            .average()
                            .getAsDouble();
    
            System.out.println(ageAvg);
        }
    }

    위에서 작성한 코드를 줄여보았다. 지역 변수만 모두 생략하고 연결하면 위와 같은 형태가 된다. filter() 메서드를 통해 남자 Member 객체를 요소로 하는 새로운 스트림을 생성하였고, mapToInt() 메서드를 통해 Member 객체를 age 값으로 매핑해서 age를 요소로 하는 새로운 스트림을 생성하였다. 그리고 average() 메서드는 age 요소들의 평균을 OptionalDouble에 저장한다. 마지막으로, OptionalDouble에서 저장된 평균값을 읽기 위하여 getAsDouble() 메서드를 호출한다.


    출처

    https://steady-coding.tistory.com/311

     

    728x90

    댓글

Designed by Tistory.