자바의 스트림(Stream)은 람다식과 함께 함수형 프로그래밍을 강화하는 데 도움을 주는 매우 유용한 기능입니다. 자바 스트림 API는 복잡한 데이터 가공 작업을 간단하고 선언적(declarative)으로 처리할 수 있습니다. 이 글에서는 스트림의 개념과 활용법, 기본 사용 방법 및 함수형 프로그래밍을 본격적으로 구현하기 위한 다양한 스트림 연산의 사용법을 상세하게 소개하겠습니다.
1. 스트림의 개념 및 활용 기본 방법
스트림(Stream)은 자바 8부터 추가된 기능으로, 데이터 소스를 처리하는 데 사용됩니다. 스트림은 다음과 같은 장점이 있습니다:
- 코드의 가독성 높이기
- 데이터 가공의 효과성 향상
- 메모리의 효율적인 활용
중간 연산(intermediate operation)과 최종 연산(terminal operation)은 스트림의 주요 연산입니다. 이 연산들을 조합하여 복잡한 데이터 처리 작업을 수행할 수 있습니다. 스트림을 사용할 때 기본적으로 아래와 같은 과정을 거칩니다:
데이터 소스 생성 -> 중간 연산 1 -> 중간 연산 2 -> ... -> 최종 연산 (결과 출력)
2. 스트림의 생성 방법
스트림은 다양한 자료구조에서 생성할 수 있으며, 주로 Collection 인터페이스의 stream() 메소드를 사용합니다.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> numberStream = numbers.stream();
또한, Stream 클래스의 of() 메소드를 이용하여 직접 스트림을 생성할 수도 있습니다.
Stream<String> stringStream = Stream.of("Java", "Stream", "Lambda");
3. 스트림 API 주요 중간 연산
스트림 중간 연산은 스트림을 반환하므로, 다른 중간 연산이나 최종 연산과 연결하여 사용할 수 있습니다. 주요 중간 연산 메소드로는 다음과 같은 것들이 있습니다:
- filter(Predicate<T> predicate): 주어진 조건에 맞는 요소만 선택
- map(Function<T, R> mapper): 각 요소를 다른 요소로 변환
- flatMap(Function<T, Stream<R> mapper): 각 요소를 여러 개의 요소로 변환하여 하나의 스트림으로 합침
- distinct(): 중복 요소를 제거한 스트림 생성
- sorted() / sorted(Comparator<? super T> comparator): 요소들을 정렬하여 스트림 생성
4. 스트림 API 주요 최종 연산
최종 연산은 스트림에서 값을 취합, 수집, 검색 등의 작업을 수행하여 결과를 출력합니다. 주요 최종 연산 메소드로는 다음과 같은 것들이 있습니다:
- forEach(Consumer<? super T> action): 각 요소에 대해 주어진 작업 수행
- toArray(): 스트림의 요소들을 배열로 변환
- reduce(BinaryOperator<T> accumulator): 누적 연산을 통해 스트림 요소들을 결합
- collect(Collector<? super T, A, R> collector): 스트림의 요소를 취합하여 컬렉션 등의 결과물로 반환
- min(Comparator<? super T> comparator): 주어진 비교자를 이용하여 최소 요소를 찾음
- max(Comparator<? super T> comparator): 주어진 비교자를 이용하여 최대 요소를 찾음
- count(): 스트림의 요소 개수
- anyMatch(Predicate<? super T> predicate): 주어진 조건에 맞는 요소가 최소한 하나라도 있는지 확인
- allMatch(Predicate<? super T> predicate): 모든 요소가 주어진 조건에 맞는지 확인
- noneMatch(Predicate<? super T> predicate): 주어진 조건에 맞는 요소가 없는지 확인
- findFirst(): 스트림에서 첫 번째 요소를 찾음 (존재할 때)
- findAny(): 스트림에서 임의의 요소를 찾음 (존재할 때)
5. 스트림 사용 예제
스트림의 강력함은 복잡한 데이터 처리 작업을 선언적(declarative)으로 표현할 수 있으며, 코드의 가독성을 높여줍니다. 이제 스트림을 사용하여 여러 가지 예제를 살펴보겠습니다.
※ 각 예제의 코드는 이전 섹션에서 설명한 연산을 적절히 조합하여 작성됩니다.
1) 데이터 필터링
스트림을 사용하여 데이터를 필터링하는 작업을 다양한 방법으로 수행할 수 있습니다. 예를 들어, 짝수만 선택하거나 단어 길이가 6 보다 큰 문자열만 선택할 수 있습니다.
2) 데이터 변환
스트림을 사용하여 데이터를 변환할 수 있습니다. 예를 들어, 정수 리스트를 각 정수의 제곱으로 구성된 리스트로 변환하거나, 문자열 리스트에서 각 문자열의 길이를 나타내는 리스트로 변환할 수 있습니다.
3) 데이터 집계
스트림을 사용하여 데이터를 집계할 수 있습니다. 예를 들어, 정수 리스트에서 최소값, 최대값, 합계, 평균 값을 구할 수 있습니다. 또한, 객체 리스트에서 특정 필드 기준으로 최소값, 최대값을 구하거나 특정 조건을 만족하는 요소들의 개수를 구할 수 있습니다.
6. 스트림과 람다식의 활용
스트림과 람다식은 자바에서 함께 활용되어 프로그램의 효율성을 높입니다. 람다식을 사용하여 함수형 인터페이스를 간결하게 표현하고, 스트림 API를 이용해 복잡한 데이터 가공 작업을 간단하게 처리할 수 있습니다.
자바의 스트림을 활용하면 코드 구조를 선언적(declarative)으로 표현하면서, 데이터 처리 작업의 효율성과 가독성을 높일 수 있습니다. 이를 통해 데이터 처리도 더욱 간결하고 효과적으로 구현할 수 있습니다.
'Programming > Java' 카테고리의 다른 글
자바의 JVM구조 (0) | 2023.08.08 |
---|---|
자바의 제네릭스(Generics)와 열거형(Enum) (0) | 2023.08.07 |
자바의 람다식 (0) | 2023.08.05 |
자바의 컬렉션 프레임워크 (0) | 2023.08.04 |
자바의 예외 처리 (0) | 2023.08.03 |