스트림과 컬렉션 모두 연속된 요소 형식의 값을 저장하는 자료구조의 인터페이스를 제공한다.
'연속된' 이란 순서와 상관없이 아무 값이나 접속하는 것이 아니라 순차적으로 값에 접근한다는 것을 의미
스트림과 컬렉션의 가장 큰 차이는 '언제 계산하느냐 '(계산 시점)로 나눌 수 있다.
자료구조 특징 | 추가 삭제 가능 여부 | 생성(경제학 예시) | |
컬렉션 | 모든 요소는 컬렉션에 추가 되기 전에 계산 |
⭕️ | 게으른 생성(요청 중심 제조) |
스트림 | 요청할 때만 요소를 계산 | ❌ | 적극적 생성(즉석 제조) |
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
스트림은 내부 반복을 사용하므로 반복 과정을 우리가 신경쓰지 않아도 된다.
내부 반복은 데이터 표현과 하드웨어를 활용한 병렬성 구현을 자동으로 선택한다.
반면 외부 반복은 병렬성을 스스로 관리해야 한다. (병렬성을 스스로 관리하는 것은 매우매우 어렵다)
[모던 자바 인 액션] 스트림 takeWhile( ), dropWhile( ), limit( ), skip( )로 슬라이싱하기 (2) | 2022.06.30 |
---|---|
[모던 자바 인 액션] 스트림 distinct(), filter() 사용법 (0) | 2022.06.30 |
[모던 자바 인 액션] 스트림의 중간연산과 최종연산 특징과 사용법 (0) | 2022.06.28 |
[모던 자바 인 액션] 🏞 스트림? 그게 뭐야? 도대체 왜 사용하는거야? (0) | 2022.06.19 |
댓글 영역