모든 값을 메모리에 저장하는 자료구조입다. 따라서 Collection에 추가하기 전에 미리 계산이 완료되어야 합니다. 외부반복을 통해 사용자가 직접 반복작업을 거쳐 요소를 가져올 수 있다.(for~each구문)
요청할때만 요소를 계산한다. 내부반복을 이용하므로 추출 요소만 선언해주면 알아서 반복처리를 진행한다. 스트림에 요소를 따로 추가하거나 제거하는 작업은 불가능하다.
Collection은 외부반복, Stream은 내부반복이다.
성능측면에서 '내부반복'이 비교적 좋다. 내부반복은 작업을 병렬처리하면서 최적화된 순서로 처리해준다. 하지만 외부반복은 명시적으로 컬렉션 항목을 하나씩 가져와 처리해야하므로 최적화에 불리하다.
따라서 Collection에서 병렬성을 이용하려면 직접 synchronized를 통해 관리해야만 한다.
연산과정이 중간과 최종으로 나뉘어진다. filter, map, limit 등 파이프라이닝이 가능한 연산을 중간연산, count, collect 등 스트림을 닫는 연산을 최종연산이라고 한다.
이 둘로 나누는 이유는 중간연산들은 스트림을 반환해야 하는데, 하나의 과정으로 병합되어 처리한 다음 ➡️ 최종연산에서 한꺼번에 처리하게 된다. 최적화는 물론 가독성측면에서도 Stream이 더 좋다.
모두 스트림을 반환한다.
Optional 클래스
: 값의 존재 여부를 표현하는 컨테이너 클래스다. null로 인한 버그를 막을 수 있다는 장점이 있다.