1. Stream API란?
- Java Stream API는 데이터를 효율적으로 처리하기 위한 함수형 프로그래밍 기법이다.
- 컬렉션(List, Set, Map, 배열 등)에 저장된 데이터를 반복문 없이 간결하고 직관적으로 처리할 수 있도록 도와준다.
- 코딩테스트에서 데이터 변환, 필터링, 정렬, 집계 등을 쉽게 할 수 있어 자주 사용된다.
2. Stream API의 특징
- 데이터 처리 간소화
for문 없이 데이터 필터링, 변환, 정렬, 반복 가능
- 함수형 프로그래밍 스타일로 코드가 더 가독성 높음
- 중간 연산(Intermediate Operation) & 최종 연산(Terminal Operation)
- 중간 연산 - 스트림을 가공 (
map(), filter(), sorted())
- 최종 연산 - 결과를 반환 (
collect(), count(), toArray())
- 내부 반복 (Internal Iteration)
for문 없이 스트림이 내부적으로 데이터를 처리
- 병렬 처리 가능 (Parallel Stream)
parallelStream()을 사용하면 멀티코어를 활용하여 성능 향상 가능
3. Stream 생성하기
1) 리스트(List) → 스트림 변환
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
2) 배열(Array) → 스트림 변환
int[] arr = {1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(arr);
3) 특정 범위 숫자 스트림 생성
IntStream rangeStream = IntStream.range(1, 10);
IntStream rangeClosedStream = IntStream.rangeClosed(1, 10);
1) map() - 데이터 변환
List<String> names = Arrays.asList("john", "jane", "jack");
List<String> upperCaseNames = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(upperCaseNames);
2) filter() - 조건에 맞는 데이터 필터링
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(evenNumbers);
3) sorted() - 정렬
List<String> words = Arrays.asList("banana", "apple", "grape");
List<String> sortedWords = words.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedWords);
4) distinct() - 중복 제거
List<Integer> nums = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> uniqueNums = nums.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(uniqueNums);
5) limit(n) - 스트림 크기 제한
List<Integer> limitedNumbers = numbers.stream()
.limit(3)
.collect(Collectors.toList());
System.out.println(limitedNumbers);
5. 최종 연산 (Terminal Operation)
1) collect() - 리스트 변환
List<String> names = Arrays.asList("john", "jane", "jack");
List<String> result = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(result);
2) count() - 요소 개수 반환
long count = names.stream()
.filter(name -> name.startsWith("j"))
.count();
System.out.println(count);
3) forEach() - 각 요소 출력
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
4) reduce() - 누적 연산
int sum = numbers.stream().reduce(0, Integer::sum);
System.out.println(sum);
6. 병렬 스트림 (Parallel Stream)
- 멀티코어 CPU를 활용하여 연산 속도를 향상시킬 수 있다.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
long count = numbers.parallelStream()
.filter(n -> n % 2 == 0)
.count();
System.out.println(count);
7. Stream과 기존 for문 비교
기존 for문
List<String> words = Arrays.asList("apple", "banana", "cherry");
List<String> result = new ArrayList<>();
for (String word : words) {
if (word.length() > 5) {
result.add(word.toUpperCase());
}
}
System.out.println(result);
Stream을 사용한 방식
List<String> result = words.stream()
.filter(w -> w.length() > 5)
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(result);
- Stream을 사용하면 코드가 더 간결하고 가독성이 좋음.
8. 코딩테스트에서 자주 쓰는 Stream 패턴
1) 배열을 리스트로 변환
int[] arr = {1, 2, 3, 4, 5};
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
2) 리스트를 배열로 변환
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int[] arr = list.stream().mapToInt(Integer::intValue).toArray();
3) 숫자 리스트의 합
int sum = list.stream().mapToInt(Integer::intValue).sum();
4) 가장 큰 값 찾기
int max = list.stream().mapToInt(Integer::intValue).max().orElse(0);
5) 가장 작은 값 찾기
int min = list.stream().mapToInt(Integer::intValue).min().orElse(0);
9. 마무리 - Stream API 정리
| 기능 | 메서드 |
|---|
| 데이터 변환 | map() |
| 필터링 | filter() |
| 정렬 | sorted() |
| 중복 제거 | distinct() |
| 리스트 변환 | collect() |
| 조건 검사 | anyMatch(), allMatch() |
| 누적 연산 | reduce() |