[아이템 45] 스트림은 주의해서 사용하라.
스트림이 제공하는 핵심 개념 중 핵심은 두 가지로 나눌 수 있습니다.
- 스트림은 데이터 원소의 유한 혹은 무한 시퀀스를 뜻합니다.
- 스트림 파이프라인은 이 원소들로 수행하는 연산 단계를 표현하는 개념입니다.
스트림은 소스 스트림으로 시작해서 종단(최종) 연산(terminal operation)으로 끝나며, 그 사이에 하나 이상의 중간 연산자가 있을 수 있습니다. 중간 연산자는 어떠한 방식으로 변환(transform) 합니다. 최종 연산은 원소를 정렬해 컬렉션에 담거나, 특정 원소 하나를 선택하거나, 모든 원소를 출력하는 식입니다.
스트림 파이프 라인은 lazy합니다. 최종 연산자가 호출 되기 전까지 실행하지 않습니다. 최종 연산에 쓰이지 않는 데이터 원소는 계산에 쓰이지 않습니다. 이러한 지연 평가는 무한 스트림을 다룰 수 있게 해줍니다. 최종 연산이 없는 스트림은 아무일도 하지 않으니(NOP) 빼먹는 일이 없도록 합시다.
스트림 API는 파이프라인 하나를 구성하는 모든 호출을 연결하여 단 하나의 표현식으로 완성할 수 있습니다. 스트림을 이용해서 다양한 기능을 구사할 수 있지만, 잘못 사용하면 읽기 어려워지고 유지보수 하기도 힘들어집니다.
스트림을 ㅊ처음 사용하면 모든 반복문을 스트림으로 바꾸고 싶겠지만, 신중하게 생각해봐야 합니다. 가독성과 유지보수, 메모리 측면에서 손해를 볼 수 있기 때문입니다.
스트림 파이프라인에서 계산을 함수 객체로 표현하는데 함수 객체로는 할 수 없지만 코드 블록으로 할 수 있는 일들이 있습니다.
- 코드 블록에서는 범위 안의 지역변수를 읽고 수정할 수 있습니다. 하지만 람다에서는 final이거난 effective final만 읽을 수 있고, 지역변수를 수정할 수 없습니다.
- 코드 블록에서는 return문을 사용해 메서드에서 빠져나가거나, break나 continue 문으로 블록 바깥의 반복문을 종료하거나 반복문을 한 번 건너뛸 수 있습니다. 또한 메서드 선언에 명시된 검사 예외를 던질 수 있습니다. 하지만 람다로는 이 중 어떤것도 할 수 없습니다.
계산 로직에서 이상의 일들을 수행을 한다면 스트림과는 맞지 않는 것입니다. 다음은 스트림과 안성 맞춤인 일들 입니다.
- 원소들의 시퀀스를 일관되게 변환한다.
- 원소들의 시퀀스를 필터링한다.
- 원소들의 시퀀스를 하나의 연산을 사용해 결합한다.
- 원소들의 시퀀스를 컬렉션에 모은다.
- 원소들의 시퀀스에서 ㅌ특정 조건을 만족하는 원소를 찾는다.