헷갈리는 스트림 vs 컬렉션 바로 알자

이상무·2022년 6월 29일
0

Modern Java in Action

목록 보기
2/2
post-thumbnail

 모던 자바 인 액션 - YES24 www.yes24.com


스트림과 컬렉션

스트림과 컬렉션 모두 연속된 요소 형식의 값을 저장하는 자료구조의 인터페이스를 제공한다.

'연속된' 이란 순서와 상관없이 아무 값이나 접속하는 것이 아니라 순차적으로 값에 접근한다는 것을 의미

👉🏾 차이점

스트림과 컬렉션의 가장 큰 차이는 '언제 계산하느냐 '(계산 시점)로 나눌 수 있다.

 자료구조 특징추가 삭제 가능 여부생성(경제학 예시)
컬렉션모든 요소는 컬렉션에 추가 되기 전에 계산 ⭕️ 게으른 생성(요청 중심 제조)
스트림요청할 때만 요소를 계산적극적 생성(즉석 제조)

👉🏾 계산 시점 예시

컬렉션 : DVD로 영화 시청 (적극적 생성)

DVD에 저장된 모든 값을 처리 후 재생할 수 있다.

스트림 : 인터넷 스트리밍으로 영화 시청 (게으른 생성)

사용자가 시청하는 부분을 몇 프레임을 미리 내려받는다. 스트림의 대부분의 값을 처리하지 않은 상태에서 미리 내려받은 프레임부터 재생할 수 있다. 비디오 재생기는 모든 프레임을 내려 받을 만큼 충분한 메모리가 없을 수도 있고 있다고 하더라도 모든 프레임을 내려받고 재생을 시작하면 내려받기위한 로딩시간이 많이 필요할 것이다.


출처: Morder Java in Action

👉🏾 소수 예제

컬렉션은 끝이 없는 모든 소수(2, 3, 5, 7, 11, ...)를 포함하려 하며 무한 루프를 돌면서 새로운 소수를 계산하고 추하하기를 반복한다. 고로 영원히 결과를 볼 수 없다. 그러나 스트림은 사용자가 요청하는 즉시 값을 계산하여 이 문제를 해결할 수 있다.


 딱 한 번만 탐색할 수 있다

반복자와 마찬가지로 스트림도 한 번만 탐색할 수 있다. 탐색된 스트림의 요소는 소비된다.탐색한 요소를 다시 탐색하려면 초기의 데이터 소스에서 새로운 스트림을 만들어야 한다. (컬렉션처럼 반복 가능한 데이터 소스여야 한다.)

예시 👇🏾

	List<String> title = Arrays.asList("Java8", "In", "Action");
      	Stream<String> s = title.stream();
        s.forEach(System.out::println);
        s.forEach(System.out::println); 
        // 👆🏾 java.lang.IllegalStateException: 스트림이 이미 소비되었거나 닫힘.

외부 반복과 내부 반복

 반복병렬성
컬렉션외부 반복스스로 관리
스트림내부 반복자동으로 선택됨

👉🏾 컬렉션의 외부 반복

List<Dish> menu = Dish.getDishes();
List<String> names = new ArrayList<>();
for( Dish dish : menu) {    // 메뉴 리스트를 명시적으로 순차 반복한다.
    names.add(dish.getName());  // 이름을 추출해서 리스트에 추가한다.
}

👉🏾 스트림의 내부 반복

List<Dish> menu = Dish.getDishes();
List<String> names = menu.stream()
	.map(Dish::getName)		// map 메서드를 getName 메서드로 파라미터화해서 요리명을 추출한다.
	.collect(Collectors.toList());	// 파이프라인을 실행한다. 반복자는 필요없다.

👉🏾 내부 반복과 외부 반복 차이 예시

A: "B, 장난감 좀 정리하자. 방바닥에 장난감 있지?"

B: "응, 공 있어"

A: "오케이, 그럼 공을 상자에 담아. 또 어떤 장난감이 있지?"

B: "인형 있어"

A: "그럼 인형 담아. 또 어떤 장난감 있지?"

B: "책 있어"

A: "그럼 책 담자. 또 어떤게 있지?"

B: "아무것도 없어"

A: "오게이 잘했다!"

위 대화는 명시적으로 컬렉션 항목을 하나씩 가져와서 처리하는 컬렉션의 외부 반복이다. 우리의 목적은 그저 모든 장난감을 상자에 전부 담는 것 인데 굳이 하나씩 처리해야 할까? 스트림의 내부 반복은 그저 "모든 장난감을 전부 상자에 담아"라고 말하면 끝이다. 또 한 손에는 인형을 다른 손에는 공을 동시에 들 수 있고, 먼저 모든 장난감을 상자 가까이 이동시킨 다음 장난감을 상자에 담는다.


출처: Mordern Java in Action

스트림은 내부 반복을 사용하므로 반복 과정을 우리가 신경쓰지 않아도 된다. 

👉🏾 반복속 병렬성

내부 반복은 데이터 표현과 하드웨어를 활용한 병렬성 구현을 자동으로 선택한다.

반면 외부 반복은 병렬성을 스스로 관리해야 한다. (병렬성을 스스로 관리하는 것은 매우매우 어렵다)

profile
이상없다 초과있다

0개의 댓글