스트림 파이프라인의 마지막에 위치하며,
스트림을 소비하고 결과를 반환하거나 출력하는 연산이다.
스트림을 한 번만 소비하고 나면 재사용할 수 없다.
결과값을 반환하거나, 출력, 저장, 집계 등의 작업을 수행한다.
종단 연산이 호출되기 전까지는 중간 연산도 실제로 실행되지 않는다 (지연 평가, lazy evaluation).
스트림의 각 요소를 소비하여 어떤 동작을 수행
List<String> list = List.of("apple", "banana", "cherry");
list.stream().forEach(System.out::println);
스트림 결과를 리스트, 맵, 문자열 등으로 수집
List<String> result = list.stream()
.filter(s -> s.contains("a"))
.collect(Collectors.toList());
Collectors::와 자주 쓰인다.
toList()(리스트로 변환), toSet(), toMap()
joining(), groupingBy(), partitioningBy()
요소 개수를 세는 연산
long count = list.stream()
.filter(s -> s.length() > 5)
.count();
특정 조건에 대한 불린 값 판단
boolean hasBanana = list.stream()
.anyMatch(s -> s.equals("banana")); // true
anyMatch: 하나라도 조건 만족
allMatch: 모두 조건 만족
noneMatch: 아무도 조건 불만족
조건에 맞는 요소를 Optional로 반환. first는 조건에 만족한 가장 첫 번째 요소만 반환하고 any는 만족한 요소 중 아무거나 반환한다.
Optional<String> first = list.stream()
.filter(s -> s.length() > 5)
.findFirst();
스트림 요소를 하나의 값으로 축소(누적), 만약 초깃값이 없으면 Optional을 반환한다.
int sum = List.of(1, 2, 3, 4).stream()
.reduce(0, (a, b) -> a + b); // 10
스트림을 배열로 변환
String[] arr = list.stream()
.toArray(String[]::new);
각각 최솟값, 최댓값을 반환함. 값이 없을 수 있으므로 Optional을 반환함.
Optional<Integer> min = numbers.stream()
.min(Integer::compareTo);
System.out.println("최솟값: " + min.get());
System.out.println();
Optional<Integer> max = numbers.stream()
.max(Integer::compareTo);
System.out.println("최댓값: " + max.get());
System.out.println();
스트림은 한 번만 소비 가능한다.
종단 연산이 실행되어야 중간 연산이 실제로 수행된다.
forEach()와 같은 연산은 부수 효과(side effect)가 생길 수 있으니 주의해서 사용해야 한다.
| 종단 연산 | 설명 | 반환 타입 |
|---|---|---|
forEach() | 각 요소 처리 (출력 등) | void |
collect() | 리스트/맵 등으로 수집 | 다양한 타입 |
count() | 요소 개수 반환 | long |
anyMatch() 등 | 조건 만족 여부 확인 | boolean |
findFirst() | 첫 번째 요소 반환 (Optional) | Optional |
reduce() | 누적값 계산 | T or Optional |
toArray() | 배열로 변환 | T[] |