Stream 이란?

 

Java8 부터 지원하는 Stream은 컬렉션, 배열등에 대해 저장되어 있는 요소들을 하나씩 참조하며 반복적인 처리를 하는 기능이다.

Stream이용 시 불필요한 for문과 그안에서 이루어 지는 if문 등의 분기 처리를 쓰지 않고 깔끔하고 직관적인 코드로 변경가능하다.

 

Stream특징

  1. Stream은 원본 데이터로 부터 데이터를 읽기만 할 뿐, 원본 데이터 자체를 변경하지 않는다
  2. Steam은 한 번 사용하면 닫혀서 재사용이 불가능하다. 필요하다면 정렬된 결과를 컬렉션이나 배열에 담아 반환할 수 있다.
  3. Stream은 작업을 내부 반복으로 처리하며 Stream을 이용한 작업이 간결할 수 있는 비결 중 하나이다. 내부 반복이라는 것은 반복문을 메서드의 내부에 숨길 수 있다는 것을 의미한다(코드상 반복문이 노출되지 않는다)

 

Stream 구조

Stream의 구조는 크게 세가지로 볼 수 있다.

  1. Stream 생성
  2. 중개 연산
  3. 최종 연산

세가지로 구성되며 중개연산은 연산 결과를 Stream 형태로 반환하기 때문에 연속적으로 연결해서 사용할 수 있다.

정리하자면 데이터소드객체집합.Stream생성().중개연산().최종연산(); 이다.

 

Stream 생성

 

Stream API는 다음과 같은 다양한 데이터 소스에서 생성이 가능하다.

  1. 컬렉션
  2. 배열
  3. 가변 매개변수
  4. 지정된 범위의 연속된 정수
  5. 특정 타입의 난수들
  6. 람다 표현식
  7. 파일
  8. 빈 스트림

 

중개연산

 

중개연산은 Stream을 전달 받아 Stream으로 반환하므로 중개 연산을 연속으로 사용이 가능하다.

또한 Stream의 중개연산은 필터-맵(filter-map)기반의 API를 사용함으로써 지연(Lazy)연산을 통해 최적화가 가능하다.

대표적인 중개 연산과 그에 따른 메소드는 다음과 같다.

  1. Stream 필터링: filter(), distinct()
  2. Stream 변환: Map(), flatMap()
  3. Stream 제한: limit(), skip()
  4. Stream 정렬: sorted()
  5. 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은 더이상 사용이 불가능하다

 

대표적인 최종연산

  1. 요소의 출력: forEach()
  2. 요소의 소모: reduce()
  3. 요소의 검색: findFirst(), findAny()
  4. 요소의 검사: anyMatch(), allMatch(), noneMatch()
  5. 요소의 통계: count(), min(), max()
  6. 요소의 연산:  sum(), average()
  7. 요소의 수집 : 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

+ Recent posts