Collection
- 데이터 저장 및 관리 : 데이터의 저장, 관리, 접근을 위한 자료 구조를 제공
- 상태를 갖는 구조 : 상태를 갖고 있으며, 데이터를 추가하거나 삭제하면 그 상태가 변화함
- 즉시 평가 : 데이터는 즉시 저장되며, 컬렉션에서 제공하는 메서드를 통해 데이터를 처리
Stream
- 연속적인 데이터 흐름 : 스트림은 데이터의 연속적인 흐름으로 데이터 소스로부터 데이터를 받아 연산을 수행하고 결과를 생성
- 지연 평가 : 중간 연산을 연결하여 파이프라인을 형성하고 최종 연산이 호출될 때까지 연산을 지연시킴
- 함수형 프로그래밍 요소 : 데이터 처리를 위한 메서드 체인 방식의 API를 제공
- 데이터소스객체집합.Stream생성().중개연산().최종연산()
반복자 스트림
- 컬렉션, 배열 등의 저장요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 하는 기능
- 컬렉션은 반복자를 통해서 각각의 원소에 접근해 원소를 가공했지만 스트림은 특정 타입의 스트림을 선언하여 필요한 형태로 가공하여 반환
공통점
- 데이터 구조화 : 데이터를 구조화하여 저장하고 관리, 데이터를 담고 있는 컬렉션을 이용해 다양한 작업을 수행 가능
- 데이터 처리 : 데이터를 처리하는 기능을 제공, 스트림은 컬렉션을 기반으로하여 데이터를 연속적으로 처리하는 방식으로 동작
- 중간 연산과 최종 연산 : 중간 연산은 데이터를 변환하거나 필터링하는 등의 작업을 수행하고, 최종 연산은 최종 결과를 생성하거나 반환
차이점
- 데이터 저장 방식 : 컬렉션은 데이터를 저장하는 자료구조를 갖고 있으며 상태를 갖음
스트림은 연속된 데이터의 흐름으로 데이터는 연산에 의해 처리
- 지연 평가의 존재 유무 : 스트림은 지연 평가를 통해 최종 연산이 호출될 때까지 연산을 지연시키지만 컬렉션은 즉시 데이터를 저장하고 처리
- 함수형 프로그래밍 요소의 유무 : 스트림은 함수형 프로그래밍의 개념을 도입하여 데이터 처리를 함수 체인으로 연결할 수 있도록 지원, 컬렉션은 가지지 않음
- 데이터 반복 처리 방법 : 컬렉션은 외부반복, 스트림은 내부 반복
외부 반복
- 명시적으로 컬렉션 항목을 하나씩 가져와서 처리함
- 병렬성을 스스로 관리해야 함
내부 반복
- 작업을 투명하게 병렬로 처리 가능
- 더 최적화된 다양한 순서로 처리 가능
- filter 나 map 같이 반복을 숨겨주는 연산 리스트가 미리 정의되어 있어야 함
- 반복을 숨겨주는 연산은 대부분 람다 표현식으로 인수를 받음
- 동작 파라미터화를 사용 가능

비유
DVD는 이미 영화가 저장되어서 판매된다. 이는 컬렉션에 비유할 수 있다.
반면 인터넷 스트리밍은 사용자가 시청하는 부분의 몇 프레임을 미리 내려받는다.
때문에 대부분의 값을 처리하지 않은 상태에서 미리 내려받은 프레임부터 재생이 가능하다.
이를 스트림으로 비유할 수 있다.
컬렉션 = DVD
- 자료구조가 포함하는 모든 값을 메모리에 저장한다.
- 컬렉션의 모든 요소는 컬렉션에 추가하기 전에 계산되어야 한다.
- 생산자 중심 → 팔기도 전에 창고를 가득 채움.
- 만약 소수를 저장하는 컬렉션을 만들 시에, 끝도 없이 모든 소수를 포함하려 할 것이므로 무한루프를 돌게 된다.
- 영화의 모든 프레임들이 미리 저장되어있는 DVD
- 적극적 생성 → 모든 값을 계산할 때까지 기다린다.
스트림 = 인터넷 스트리밍
- 요청할 때만 요소를 계산한다. 고정된 자료구조. → 스트림에 요소를 추가하거나 제거할 수 없다.
- 사용자가 요청하는 값만 스트림에서 추출한다.
- 생성자와 소비자의 관계를 형성한다.
- 게으른 생성 → 필요할 때만 값을 계산한다.

예시
컬렉션
public class CollectionExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = 0;
for (int num : numbers) {
if (num % 2 == 0) { // 짝수 필터링
int squared = num * num; // 제곱 연산
sum += squared; // 총 합 계산
}
}
System.out.println("짝수의 제곱 합: " + sum);
}
}
스트림
public class StreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.filter(num -> num % 2 == 0) // 짝수 필터링
.mapToInt(num -> num * num) // 제곱 연산
.sum(); // 총 합 계산
System.out.println("짝수의 제곱 합: " + sum);
}
}
두 방식은 동일한 결과를 얻지만 컬렉션은 명시적인 루프를 사용하여 각 단계를 직접 구현
스트림은 연산들을 메서드 체인으로 연결하여 간결하게 표현
결론
- 컬렉션은 데이터를 저장하고 관리하는 구조를 제공하는 반면, 스트림은 데이터의 연속적인 흐름을 다루며 함수형 프로그래밍 요소를 갖고 있어 데이터 처리 방식이 다름
- 컬렉션과 스트림은 각각의 특징을 가지고 있어 데이터 처리 방식이나 목적에 따라 선택하여 사용 가능
