Stream 이란?
스트림 파이프라인
- 0 또는 다수의 중개 오퍼레이션 (intermediate operation)과 한개의 종료 오퍼레이션 (terminal operation)으로 구성한다.
- 스트림의 데이터 소스는 오직 터미널 오퍼네이션을 실행할 때에만 처리한다.
- 종료 오퍼레이션이 있기 전까지 실행하지 않는다.
numbers.stream().map((s) -> {
System.out.println(s);
return s.toUpperCase();
})
- 위에서 System.out.println(s); 가 실행되지 않는다. -> 종료 오퍼레이션이 없기 때문이다.
중개 오퍼레이션
- Stream을 리턴한다.
- Stateless / Stateful 오퍼레이션으로 더 상세하게 구분할 수도 있다. (대부분은 Stateless지만 distinct나 sorted 처럼 이전 소스 데이터를 참조해야 하는 오퍼레이션은 Stateful 오퍼레이션이다.)
- filter, map, limit, skip, sorted, ...
종료 오퍼레이션
- Stream을 리턴하지 않는다.
- collect, allMatch, count, forEach, min, max, ...
Stream API
걸러내기
// spring 으로 시작하는 수업
springClasses .stream()
.filter(oc -> oc.getTitle().startsWith("spring"))
.forEach(oc -> System.out.println(oc.getId()));
// close 되지 않은 수업
springClasses.stream()
.filter(oc -> !oc.isClosed()) // .filter(Predicate.not(OnlineClass::isClosed)) 로 대체할 수 있다.
.forEach(oc -> System.out.println(oc.getId()));
변경하기
- Map(Function) 또는 FlatMap(Function)
- 예) 각각의 Post 인스턴스에서 String title만 새로운 스트림으로
- 예) List을 String의 스트림으로
- ex>
// 수업 이름만 모아서 스트림 만들기
springClasses.stream()
.map(ec -> oc.getTitle()) // String 타입으로 변경
.forEach(oc -> System.out.println(oc.getId()));
List<List<OnlineClass>> lists = new ArrayList<>();
lists.add(springClasses);
lists.add(javaClasses);
// 두 수업 목록에 들어있는 모든 수업 아이디 출력
lists.stream()
.flatMap(list -> list.stream())
.forEach(oc -> System.out.println(oc.getId()));
생성하기
- generate(Supplier) 또는 Iterate(T seed, UnaryOperator)
- 예) 10부터 1씩 증가하는 무제한 숫자 스트림
- 예) 랜덤 int 무제한 스트림
제한하기
- limit(long) 또는 skip(long)
- 예) 최대 10개의 요소가 담긴 스트림을 리턴한다.
- 예) 앞에서 10개를 뺀 나머지 스트림을 리턴한다.
- ex>
Stream.iterate(10, i -> i + 1)
.skip(10)
.limit(10)
.forEach(System.out::println);
스트림에 있는 데이터가 특정 조건을 만족하는지 확인
- anyMatch(), allMatch(), nonMatch()
- 예) k로 시작하는 문자열이 있는지 확인한다. (true 또는 false를 리턴한다.)
- 예) 스트림에 있는 모든 값이 10보다 작은지 확인한다.
- ex>
javaClasses.stream()
.anyMatch(oc -> oc.getTitle().contains("Test"));
개수 세기
- count()
- 예) 10보다 큰 수의 개수를 센다.
스트림을 데이터 하나로 뭉치기
- reduce(identity, BiFunction), collect(), sum(), max()
- 예) 모든 숫자 합 구하기
- 예) 모든 데이터를 하나의 List 또는 Set에 옮겨 담기
정렬하기
- sorted 를 이용해서 쉽게 정렬을 할 수 있다.
.stream().sorted(
Comparator
.comparing(User::getUserAge)
.thenComparing(User::getUsername)
.thenComparing(User::getuserId)
).collect(Collectors.toList());
flatMap
- 만약 Order 라는 클래스가 있고 Order 는 List 를 갖는다고 했을 때 아래와 같이 flatMap 을 사용할 수 있다.
List<OrderLine> mergedOrderLines = orders.stream() // Stream<Order>
.map(Order::getOrderLines) // Stream<List<OrderLine>>
// .map(List::stream) // Stream<Stream<OrderLin>>
.flatMap(List::stream) // Stream<OrderLine>
.collect(Collectors.toList());
REFERENCES