Java Stream API 기초 완벽 이해하기
Java 8 이후 Java 개발 스타일을 완전히 바꿔버린 핵심 기능이 바로:
Stream API
입니다.
현대 Java 실무에서는:
- 데이터 가공
- 리스트 변환
- 필터링
- 집계 처리
- 병렬 처리
전부 Stream 기반으로 작성하는 경우가 많습니다.
예:
list.stream()
.filter(x -> x > 10)
.map(x -> x * 2)
.forEach(System.out::println);
이런 코드가 바로 Stream 스타일입니다.
처음 보면:
“for문 없애는 문법?”
처럼 보일 수 있지만,
실제로 Stream은:
- 내부 반복(Internal Iteration)
- Lazy Evaluation
- Pipeline
- 함수형 프로그래밍
- 병렬 처리
까지 연결되는 매우 중요한 Java 핵심 기능입니다.
이번 글에서는:
- Stream이란?
- 왜 등장했는가
- 내부 반복 구조
- map/filter/reduce
- lazy evaluation
- pipeline 구조
- 실무 사용 전략
까지 깊게 정리해보겠습니다.
1. Stream이란?
Stream API 는:
데이터를 함수형 방식으로 처리하기 위한 API
입니다.
2. 핵심 목표
매우 중요.
“데이터 처리 로직을 선언적으로 작성”
하는 것.
3. 기존 Java 방식
예:
List<Integer> result =
new ArrayList<>();
for (Integer n : numbers) {
if (n > 10) {
result.add(n * 2);
}
}
4. 문제점
로직보다:
반복 제어 코드
가 더 많음.
즉:
- iterator
- loop
- 임시 변수
등 보일러플레이트 증가.
5. Stream 방식
List<Integer> result =
numbers.stream()
.filter(n -> n > 10)
.map(n -> n * 2)
.toList();
6. 훨씬 선언적
핵심:
무엇을 할지 중심
으로 표현.
7. Stream은 Collection이 아니다
매우 중요.
많은 초보자가 헷갈림.
8. Collection vs Stream
| 항목 | Collection | Stream |
| 목적 | 데이터 저장 | 데이터 처리 |
| 특징 | mutable 가능 | 일회성 처리 |
| 반복 방식 | 외부 반복 | 내부 반복 |
9. Stream은 “흐름”
즉:
데이터 자체가 아니라
데이터 처리 파이프라인
입니다.
10. Stream 생성
대표 방법:
list.stream()
11. 배열도 가능
Arrays.stream(arr)
12. Stream.of()
Stream.of(1, 2, 3)
13. 핵심 구조
Stream은 보통:
생성
↓
중간 연산
↓
최종 연산
구조.
14. 예시 전체 흐름
list.stream()
.filter(x -> x > 10)
.map(x -> x * 2)
.forEach(System.out::println);
15. 분석
| 단계 | 역할 |
| stream() | Stream 생성 |
| filter() | 중간 연산 |
| map() | 중간 연산 |
| forEach() | 최종 연산 |
16. 중간 연산(Intermediate Operation)
대표:
- filter
- map
- sorted
- distinct
17. 특징
매우 중요.
중간 연산은 즉시 실행 안 됨
18. 이것이 Lazy Evaluation
Lazy evaluation 이란:
실제 필요할 때까지 실행 미루는 것
입니다.
19. 예시
list.stream()
.filter(x -> {
System.out.println(x);
return x > 10;
});
20. 실행 결과?
아무것도 출력 안 됨
왜냐하면:
최종 연산 없음
이기 때문.
21. 최종 연산(Terminal Operation)
대표:
- forEach
- collect
- count
- reduce
- toList
22. 최종 연산 등장 시
그제서야:
Pipeline 실행 시작
됩니다.
23. 이것이 Stream Pipeline
매우 중요.
데이터
↓
filter
↓
map
↓
collect
연결 구조.
24. filter()
대표 중간 연산.
25. 의미
조건 기반 필터링
26. 예시
.filter(x -> x > 10)
27. 내부적으로 Predicate 사용
즉:
boolean 반환 함수
사용.
28. map()
매우 중요.
29. 의미
데이터 변환(transform)
입니다.
30. 예시
.map(x -> x * 2)
31. 내부적으로 Function 사용
입력 → 출력 변환
수행.
32. forEach()
최종 연산.
33. 의미
데이터 소비
입니다.
34. 내부적으로 Consumer 사용
입력 소비
반환 없음
35. collect()
실무에서 매우 중요.
예:
.collect(Collectors.toList())
36. 의미
결과 수집
입니다.
37. reduce()
함수형 핵심 연산.
38. 예시
int sum =
list.stream()
.reduce(0, (a, b) -> a + b);
39. 의미
누적 계산
입니다.
40. 내부 반복(Internal Iteration)
매우 중요.
기존 for문:
개발자가 반복 제어
↓
외부 반복
41. Stream은?
JVM이 반복 제어
↓
내부 반복
42. 왜 중요할까?
JVM이:
- 최적화
- 병렬 처리
- lazy execution
하기 쉬워짐.
43. 병렬 Stream
예:
list.parallelStream()
44. 의미
멀티코어 병렬 처리
시도.
45. 하지만 주의점 많음
실무에서는:
- 순서 문제
- race condition
- overhead
때문에 무조건 빠르진 않음.
46. Stream 특징
| 특징 | 설명 |
| 선언형 스타일 | O |
| 내부 반복 | O |
| Lazy Evaluation | O |
| 함수형 프로그래밍 지원 | O |
47. Stream은 한 번만 사용 가능
매우 중요.
Stream<Integer> s =
list.stream();
s.count();
s.count();
↓
IllegalStateException
가능.
48. 왜 그럴까?
Stream은:
일회성 파이프라인
이기 때문.
49. Optional과도 연결
예:
findFirst()
findAny()
max()
는:
Optional 반환
가능.
50. 실무에서 자주 하는 실수
1) Stream 과용
복잡한 로직은 가독성 저하.
2) 디버깅 어려움
Pipeline 너무 길어지면 힘듦.
3) 병렬 Stream 남용
오히려 느려질 수 있음.
4) side effect 발생
람다 내부 상태 변경 주의.
51. side effect 예시
안 좋은 예:
list.stream()
.forEach(x -> result.add(x));
멀티스레드 시 위험 가능.
52. Stream vs for문
| 항목 | for문 | Stream |
| 제어 | 직접 | 선언형 |
| 가독성 | 단순 반복 강점 | 데이터 처리 강점 |
| 디버깅 | 쉬움 | 어려울 수 있음 |
| 병렬화 | 직접 구현 | parallel 지원 |
53. 핵심 흐름 요약
Collection
↓
Stream 생성
↓
중간 연산(filter/map)
↓
최종 연산(collect/reduce)
↓
실행
54. 가장 중요한 핵심 한 줄
Stream은
“데이터를 선언형·함수형 방식으로 처리하기 위한 파이프라인 API”
입니다.
55. 정리
Stream API는 단순 for문 대체 문법이 아닙니다.
실제로는:
- 함수형 프로그래밍
- Lambda
- Lazy Evaluation
- Pipeline
- 내부 반복
- 병렬 처리
전체와 연결되는 Java 8 이후 핵심 기능입니다.
특히 실무에서는:
- map/filter/reduce
- 내부 반복
- side effect 주의
- parallelStream 사용 기준
- Stream 가독성 관리
를 정확히 이해하는 것이 매우 중요합니다.
다음 글에서는:
Stream 중간 연산 / 최종 연산
을 lazy evaluation 내부 동작, short-circuit, stateful/stateless 연산, pipeline 최적화까지 포함해서 깊게 정리해보겠습니다.
'language > java' 카테고리의 다른 글
| Java Collector 활용 완벽 이해하기 (0) | 2026.05.28 |
|---|---|
| Java Method Reference(::) 완벽 이해하기 (0) | 2026.05.28 |
| Java 함수형 인터페이스(Function, Predicate, Consumer 등) 완벽 이해하기 (0) | 2026.05.27 |
| Java 익명 클래스 vs 람다 완벽 이해하기 (1) | 2026.05.27 |
| Java 람다 표현식(Lambda) 완벽 이해하기 (0) | 2026.05.27 |
댓글