JAVA

[JAVA] Steam의 특징과 컬랙션과 차이

이루나을 2024. 3. 12. 16:27

스트림(Stream)이란?

다양한 방식으로 저장된 데이터를 공통된 방식으로 처리하기 위한 API

파일, 컬랙션, 배열 등의 여러 종류의 데이터 형식이 있는데

이를 접근하기 위해서는 iteration, for-each 문 등 각각 다른 방식으로 접근해야 한다.(정형화된 처리 패턴이 없다)

이는 코드의 가독성이 떨어지며 재사용성도 떨어지는 문제점이 있다.

이를 해결하기 위해 공통의 처리 패턴을 개발했는데 그게 Stream API다

컬랙션이랑은 뭐가 달라?

컬렉션 : 현재 자료구조가 포함된 모든 데이터를 메모리에 올린다!!, 올릴 때부터  => 미리 다 만들어두고 하나씩 가져다 쓰는 DVD 방식 ex) List, Queue, Set

스트림 : 컬렉션의 요소를 하나씩 참조하여 사용자가 요청한 요소만 가져다 준다. 생산자 - 소비자 관계

 

스트림은 한번의 탐색만 할 수 있다.

스트림은 반복자처럼 한번 탐색한 요소를 다시 찾기 위해서는 또 다른 stream을 만들어야 한다.

 java.lang.IllegalStateException 발생

 

 

컬렉션은 데이터를 추가, 수정, 삭제를 직접 수행할 수 있다.

하지만 스트림은 데이터를 변경하지 않는다!! 그저 원본데이터를 유지한 상태로 원본 데이터에 대한 처리 과정(필터링, 매핑, 정렬 등)을 정의하는 데 사용된다.

 

반복하는 방식이 다르다

컬렉션: 외부 반복

직접 요소를 가지고 와 작업해야한다.

List<Dish> menu = .....
List<String> names = new ArrayList<>();
for (Dish dish : menu) {
  names.add(dish.getName());
}

요소(Dish)를 가지고 와 작업한다

 

스트림: 내부 반복

반복을 알아서 처리한다. 어떤식으로 처리할지만 결정해주면 된다

List<String> names = menu.stream()
                        .map(Dish::getName)
                        .collect(toList());

내부반복으로 처리하면 병렬성 구현을 자동으로 해줘 최적화된 처리가 가능하다.

 

 

 

 

스트림의 처리 방식

1. 데이터 소스를 중 필터에 해당하는 데이터만 가지고 온다

2. map을 통해 각 요소를 처리하는 메소드를 설정한다.

3. 연산한다 ex) .toList()

 

ex)

        return memberRepository.findAll().stream()
                .filter(Member::isActiveRole)
                .map(MemberEnrollInfoResponse::from)
                .toList();

1. memberRepository에서 findAll로 Member를 가져온다

2. 필터(Member::isActiveRole)가 true인 값만 설정한다

3. MemberEnrollInfoResponse::from을 통해 각 요소의 메소드 처리한다.

    public static MemberEnrollInfoResponse from(Member member) {
        return new MemberEnrollInfoResponse(
                member.getId(),
                member.getName(),
                member.getPosition(),
                member.getGeneration().getNumber(),
                member.getRole()
        );
    }

4. 연산한다 toList()