스트림 연산은 크게 두 가지로 나뉜다:
중간 연산 (Intermediate Operation)
→ 스트림을 가공하며, 스트림을 반환한다. Lazy(지연 연산) 특성을 가진다.
최종 연산 (Terminal Operation)
→ 스트림을 소비하며, 결과를 반환하거나 출력한다.
설명: 조건에 맞는 요소만 필터링
예제:
Stream.of(1, 2, 3, 4, 5)
.filter(n -> n % 2 == 0)
.forEach(System.out::println); // 2, 4
설명: 요소를 다른 형태로 변환
예제:
Stream.of("java", "stream")
.map(String::toUpperCase)
.forEach(System.out::println); // JAVA, STREAM
List<List<String>> nestedList = List.of(List.of("a", "b"), List.of("c"));
nestedList.stream()
.flatMap(List::stream)
.forEach(System.out::println); // a, b, c
설명: 중복 제거 (equals와 hashCode 기준)
예제:
Stream.of(1, 2, 2, 3, 1)
.distinct()
.forEach(System.out::println); // 1, 2, 3
설명: 기본 정렬 또는 Comparator를 이용한 정렬
예제:
Stream.of(3, 1, 2)
.sorted()
.forEach(System.out::println); // 1, 2, 3
Stream.of("apple", "banana", "cherry")
.sorted(Comparator.reverseOrder())
.forEach(System.out::println); // cherry, banana, apple
설명: 중간 단계에서 요소를 엿보고 디버깅할 때 사용 (최종 연산 없으면 동작 안 함)
예제:
Stream.of(1, 2, 3)
.peek(n -> System.out.println("중간 확인: " + n))
.map(n -> n * 2)
.forEach(System.out::println);
설명: 앞에서부터 n개 요소만 가져옴
예제:
Stream.of(1, 2, 3, 4, 5)
.limit(3)
.forEach(System.out::println); // 1, 2, 3
설명: 앞에서 n개 요소를 건너뜀
예제:
Stream.of(1, 2, 3, 4, 5)
.skip(2)
.forEach(System.out::println); // 3, 4, 5
System.out.println("9. takeWhile - 5보다 작은 동안만 선택");
numbers2.stream()
.takeWhile(n -> n < 5)
.forEach(n -> System.out.print(n + " "));
System.out.println("\n") System.out.println("10. dropWhile - 5보다 작은 동안 건너뛰기");
numbers2.stream()
.dropWhile(n -> n < 5)
.forEach(n -> System.out.print(n + " "));
| 특징 | 설명 |
|---|---|
| 지연 평가 (Lazy Evaluation) | 최종 연산이 실행되기 전까지는 실제 수행되지 않음 |
| 스트림 반환 | 중간 연산은 스트림을 계속 반환하기 때문에 체이닝 가능 |
| 변형 및 필터링 | 데이터를 가공하거나 필요한 조건만 추출 가능 |
자바 스트림의 중간 연산은 데이터를 "흐름처럼" 가공할 수 있게 해주는 강력한 도구이다. filter, map, sorted 등을 잘 활용하면 더 깔끔하고 함수형 스타일의 코드를 작성할 수 있다.