스트림 API 는 다량의 데이터 처리 작업을 돕고자 자바 8에 추가되었다. 이 API 가 제공하는 추상 개념 중 핵심은 다음 두 가지다.
스트림 안의 데이터 원소들은 객체 참조나 기본 타입 값이며 기본 타입 값은 int, long, doulble 세 가지를 지원한다. 대표적으로 컬렉션, 배열, 파일, 정규표현식 패턴 매처, 난수 생성기, 다른 스트림이 있다.
스트림 파이프라인은 소스 스트림에서 시작해서 종단 연산으로 끝난다. 그 사이에 하나 이상의 중간 연산이 있을 수 있다. 각 중간 연산은 스트림을 어떠한 방식으로 변환한다. 중간 연산들은 모두 한 스트림을 다른 스트림으로 변환하는데 변환된 스트림의 원소 타입은 변환 전 스트림의 원소 타입과 같을 수도 다를 수도 있다. 종단 연산은 막 중간 연산이 내놓은 스트림에 최후 연산을 가한다.
스트림 파이프라인은 지연평가(Lazy Evaluation)된다. 평가는 종단 연산이 호출될 때 이루어진다. 즉 종단 연산이 없다면 스트림 파이프라인은 아무 일도 하지 않는 명령어인 no-op 과 같다는 뜻이다. 종단 연산에 쓰이지 않은 데이터 원소는 계산에 쓰이지 않는다.
public static void main(String[] args) {
Stream<String> words = Arrays.stream(new String[]{"abc", "bca" , "bbb", "bvc"});
words.collect(groupingBy(word -> alphabetize(word))).values().stream().forEach(g -> System.out.println(g.size() + " : " + g));
}
private static String alphabetize(String s) {
char[] a = s.toCharArray();
Arrays.sort(a);
return new String(a);
}
위 코드는 스트림 변수를 알파벳 아나그램으로 만들어 그룹을 지어 출력한다. 스트림 파이프라인은 되풀이되는 계산을 함수 객체로 표현한다. 반면 반복 코드에서는 코드 블럭을 사용해 표현한다.
한 데이터가 파이프라인의 여러 단계를 통과할 때 이 데이터의 각 단계에서의 값들에 동시에 접근하기 어렵다. 스트림 파이프라인은 한 값을 다른 값에 매핑하고 나면 원래의 값을 잃는 구조이기 때문이다.