자바
자바 - 스트림
개발자 포비
2024. 12. 9. 21:58
Java Stream
개요
스트림(Stream)은 데이터를 처리하기 위한 연속적인 흐름을 추상화한 인터페이스입니다.
스트림의 동작 단계
- 생성(Creation)
- 가공(Intermediate Operations)
- 소비(Terminal Operations)
예시:
List<String> names = Arrays.asList("Kim", "Park", "Lee", "Choi");
names.stream() // 생성
.filter(name -> name.length() > 3) // 가공
.forEach(System.out::println); // 소비
스트림의 특징
지연 연산 (Lazy Evaluation)
Stream<String> stream = names.stream()
.filter(name -> {
System.out.println("필터링: " + name);
return name.length() > 3;
})
.map(name -> {
System.out.println("매핑: " + name);
return name.toUpperCase();
});
// 여기까지는 실제 연산이 수행되지 않음
stream.forEach(System.out::println); // 이때 실제 연산 수행
일회성 사용
Stream<String> stream = names.stream();
stream.forEach(System.out::println);
// stream.count(); // IllegalStateException 발생
장점
1) 가독성 향상
// 기존 방식
List<Integer> evenNumbers = new ArrayList<>();
for (int i = 0; i < numbers.size(); i++) {
if (numbers.get(i) % 2 == 0) {
evenNumbers.add(numbers.get(i));
}
}
// 스트림 사용
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
2) 코드 유연성
// 조건 추가가 용이
numbers.stream()
.filter(n -> n % 2 == 0)
.filter(n -> n > 10)
.filter(n -> n < 100)
.collect(Collectors.toList());
3) 간편한 병렬 처리
numbers.parallelStream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
단점
1) 성능 오버헤드: 간단한 연산의 경우 전통적인 for문이 더 빠를 수 있음
2) 디버깅 어려움: 스택 트레이스가 복잡해져 오류 추적이 어려울 수 있음
활용 예시
List<User> users = Arrays.asList(
new User("Kim", 25),
new User("Park", 30),
new User("Lee", 35)
);
// 나이가 30 이상인 사용자의 이름을 대문자로 변환하여 정렬
List<String> result = users.stream()
.filter(user -> user.getAge() >= 30)
.map(User::getName)
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());