Stream 이란?
Java8 부터 지원하는 Stream은 컬렉션, 배열등에 대해 저장되어 있는 요소들을 하나씩 참조하며 반복적인 처리를 하는 기능이다.
Stream이용 시 불필요한 for문과 그안에서 이루어 지는 if문 등의 분기 처리를 쓰지 않고 깔끔하고 직관적인 코드로 변경가능하다.
Stream특징
- Stream은 원본 데이터로 부터 데이터를 읽기만 할 뿐, 원본 데이터 자체를 변경하지 않는다
- Steam은 한 번 사용하면 닫혀서 재사용이 불가능하다. 필요하다면 정렬된 결과를 컬렉션이나 배열에 담아 반환할 수 있다.
- Stream은 작업을 내부 반복으로 처리하며 Stream을 이용한 작업이 간결할 수 있는 비결 중 하나이다. 내부 반복이라는 것은 반복문을 메서드의 내부에 숨길 수 있다는 것을 의미한다(코드상 반복문이 노출되지 않는다)
Stream 구조
Stream의 구조는 크게 세가지로 볼 수 있다.
- Stream 생성
- 중개 연산
- 최종 연산
세가지로 구성되며 중개연산은 연산 결과를 Stream 형태로 반환하기 때문에 연속적으로 연결해서 사용할 수 있다.
정리하자면 데이터소드객체집합.Stream생성().중개연산().최종연산(); 이다.
Stream 생성
Stream API는 다음과 같은 다양한 데이터 소스에서 생성이 가능하다.
- 컬렉션
- 배열
- 가변 매개변수
- 지정된 범위의 연속된 정수
- 특정 타입의 난수들
- 람다 표현식
- 파일
- 빈 스트림
중개연산
중개연산은 Stream을 전달 받아 Stream으로 반환하므로 중개 연산을 연속으로 사용이 가능하다.
또한 Stream의 중개연산은 필터-맵(filter-map)기반의 API를 사용함으로써 지연(Lazy)연산을 통해 최적화가 가능하다.
대표적인 중개 연산과 그에 따른 메소드는 다음과 같다.
- Stream 필터링: filter(), distinct()
- Stream 변환: Map(), flatMap()
- Stream 제한: limit(), skip()
- Stream 정렬: sorted()
- Stream 연산 결과 확인 : peek()
대표적인 중계 연산 메소드
| 메소드 | 설명 |
| Stream<T> filter(Predicate<? super T> predicate) | 해당 스트림에서 주어진 조건(predict)에 맞는 요소만으로 구성된 새로운 스트림을 반환한다 |
| <R> Stream<R>map(Function<? super T, ?extends R> mapper |
해당 스트림의 요소들을 주어진 함수에 인수로 전달하여, 그 반환값으로 이루어진 새로운 스트림을 반환한다 |
| <R>Stream<R>flatMap(Function<? super,T,> extends Stream<? extends R>> mapper) |
해당 스트림의 요소가 배열일 경우, 배열의 각 요소를 주어진 함수에 인수로 전달하여, 그 반환값으로 이루어진 새로운 스트림을 반환한다 |
| Stream<T> distinct() | 해당 스트림에서 중복된 요소가 제거된 새로운 스트림을 반환한다 내부적으로 Object클래스의 equals() 메소드를 사용한다 |
| Stream<T> limit(long maxSize) | 해당 스트림에서 전달된 개수만큼의 요소만으로 이루어진 새로운 스트림을 반환한다 |
| Stream<T> peek(Consumer<? super T> action | 결과 스트림으로부터 각 요소를 소모하여 추가로 명시된 동작을 수행하여 새로운 스트림을 생성하여 반환한다 |
| Stream<T>skip(long n) | 해당 스트림의 첫 번째 요소부터 전달된 개수만큼의 요소를 제외한 나머지 요소만으로 이루어진 새로운 스트림을 반환한다 |
| Stream<T>sorted() Stream<T>sorted(Comparator<? super T> comparator) |
비교자를 전달하지 않으면 영문사전 순으로 정렬한다 해당 스트림을 주어진 비교자를 이용하여 정렬한다 |
최종연산
최종연산은 앞서 중개 연산을 통해 만들어진 stream에 있는 요소들에 대해 마지막으로 각 요소를 소모하여 최종결과를 표시한다.
즉 지연되어있던 모든 중개연산들이 최종 연산 시에 모두 수행되는 것이다. 이렇게 최종 연산 시에 모든요소를 소모한 해당 stream은 더이상 사용이 불가능하다
대표적인 최종연산
- 요소의 출력: forEach()
- 요소의 소모: reduce()
- 요소의 검색: findFirst(), findAny()
- 요소의 검사: anyMatch(), allMatch(), noneMatch()
- 요소의 통계: count(), min(), max()
- 요소의 연산: sum(), average()
- 요소의 수집 : collect()
대표적인 최종 연산 메소드
| 메소드 | 설명 |
| void forEach(Consumer<?super T> action) | 스트림의 각 요소에 대해 해당 요소를 소모하여 명시된 동작을 수행한다 |
| Optional<T> reduce(BinaryOperator<T> accumulator) T reduce(T identity, BinaryOperator<T> accumulator) |
처음 두 요소를 가지고 연산을 수행한 뒤 그 결과와 다음 요소를 가지고 또 다시 연산을 수행한다 이런 식으로 해당 스트림의 모든 요소를 소모하여 연산을 수행하고, 그 결과를 반환한다. |
| Optional<T>findFirst() Optional<T>findAny() |
해당 스트림에서 첫 번째 요소를 참조하는 Optional 객체를 반환한다. (findAny() 메소드는 병렬 스트림일 때 사용한다.) |
| boolean anyMatch(Predicate<? super T> predicate) | 해당 스트림의 일부 요소가 특정 조건을 만족할 경우에 true를 반환한다. |
| boolean allMatch(Predicate<? super T> predicate) | 해당 스트림의 모든 요소가 특정 조건을 만족할 경우에 true를 반환한다. |
| boolean noneMatch(Predicate<? super T> predicate) | 해당 스트림의 모든 요소가 특정 조건을 만족하지 않을 경우에 true를 반환한다. |
| long count() | 해당 스트림의 요소의 개수를 반환한다. |
| Optional<T> max(Comparator<? super T>comparator) | 해당 스트림의 요소 중에서 가장 큰 값을 가지는 요소를 참조하는 Optional 객체를 반환한다. |
| Optional<T>min(Comparator<? super T>comparator) | 해당 스트림의 요소 중에서 가장 작은 값을 가지는 요소를 참조하는 Optional 객체를 반환한다. |
| T sum() | 해당 스트림의 모든 요소에 대해 합을 구하여 반환한다. |
| Optional<T> average() | 해당 스트림의 모든 요소에 대해 평균값을 구하여 반환한다. |
| <R,A>R collect(Collector<? super T,A,R> collector) | 인수로 전달되는 Collectors객체에 구현된 방법대로 스트림의 요소를 수집한다. |
출처
'Spring' 카테고리의 다른 글
| [JPA] OSIV 와 성능 최적화 (0) | 2023.06.08 |
|---|---|
| [SpringBoot] @MappedSuperclass (0) | 2023.05.21 |
| [SpringBoot] 싱글톤(Singleton) 이란? (0) | 2023.05.12 |
| [java] Dependency Injection 개념 (0) | 2023.05.11 |
| [SpringSecurity] AccessDeniedHandler (0) | 2023.05.09 |