스트림 활용 에제 Model

- Transaction


- Trader

- 예제 소스

'Java8 > Java 8 in Action' 카테고리의 다른 글

병렬 데이터 처리와 성능  (0) 2017.06.29
스트림으로 데이터 수집  (0) 2017.06.29
스트림 활용  (0) 2017.06.26
스트림 소개  (0) 2017.06.16
람다 표현식  (0) 2017.06.15

5. 스트림 활용

데이터를 어떻게 처리할지는 스트림 API가 관리.

편리하게 데이터 관련 작업 가능.

스트림 API 내부적으로 다양한 최적화가 이루어질 수 있음.

스트림 API는 내부 반복 뿐 아니라 코드를 병렬로 실행할지 여부도 결정 가능.

스트림 API가 지원하는 연산을 이용하여 필터링, 슬라이싱, 매핑, 검색, 매칭, 리듀싱 등 다양한 데이터 처리 질의 표현 가능.


1. 필터링과 슬라이싱

1.1 프레디케이트로 필터링

- filter 메서드는 프레디케이드(boolean을 반환하는 함수)를 인수로 받아 프레디케이트와 일치하는 모든 요소를 포함하는 스트림 반환.


1.2 고유 요소 필터링

- 고유 요소로 이루어진 스트림을 반환하는 distinct 메서드 지원.

> 고유 여부는 스트림에서 만든 객체의 hashCode, equals로 결정됨.


1.3 스트림 축소

- 주어진 사이즈 이하의 크기를 갖는 새로운 스트림을 반환하는 limit 메서드 지원.

- 스트림이 정렬되어 있으면 최대 n개의 요소 반환 가능.


1.4 요소 건너뛰기

- 처음 n개의 요소를 제외한 스트림을 반환하는 skip 메서드 지원.

- limit과 skip은 상호 보완적 연산을 수행.


2. 매핑

- 특정 객체에서 특정 데이터를 선택하는 작업.

- 스트림 API의 map과 flatMap 메서드는 특정 데이터를 선택하는 기능 제공.


2.1 스트림의 각 요소에 함수 적용

- 스트림은 함수를 인수로 받는 map 메서드 지원.

- 인수로 제공된 함수는 각 요소에 적용. 함수를 적용한 결과가 새로운 요소로 매핑.

> 이 과정은 기존의 값을 "고친다 modify"라는 개념 보다 "새로운 버전 생성"이라는 개념에 가까움.

> "변환 transforming"에 가까운 "매핑 mapping"이라는 단어 사용.


2.2 스트림 평면화

- 스트림의 각 값을 다른 스트림으로 만든 다음 모든 스트림을 하나의 스트림으로 연결하는 메서드를 flatMap 메서드라 함.

- flatMap은 객 배열을 스트림이 아니라 스트림의 콘텐츠로 매핑함.

> 즉, map과 달리 faltMap은 하나의 평면화된 스트림을 반환.


3. 검색과 매칭

- 특정 속성이 데이터 집합에 있는지 여부를 검색

- allMatch, anyMatch, noneMatch, findFirst, findAny등 다양한 유틸리티 메서드 제공.


3.1 프레디케이트가 적어도 한 요소와 일치하는지 확인

- 프레디케이트가 주어진 스트림에 적어도 한 요소와 일치하는지 확인할 때 anyMatch 메서드 이용.

- anyMatch는 boolean 반환하는 최종 연산.


3.2 프레디케이트가 모든 요소와 일치하는지 확인

- 프레디케이트가 주어진 스트림의 모든 요소와 일치하는지 확인 할 때 allMatch 메서드 이용.

- 프레디케이드가 주어진 스트림의 일치하는 요소가 없는 확인 할 때 noneMatch 메서드 이용. (allMatch 와 반대 연산)

- anyMatch, allMatch, noneMatch 세 가지 메서드는 스트림 쇼트서킷 기법, 즉 자바의 &&, ||와 같은 연산.


쇼트서킷이란?

- 여러 and 연산으로 연결된 커다란 boolean 표현식을 평가한다고 가정할 때, 표현식에서 하나라도 거짓이라는 결과가 나오면 나머지 표현식의 결과와 상관없이 전체 결과도 거짓이 됨.

> 이러한 상황을 쇼트서킷이라 부름.


3.3 요소 검색

- 현재 스트림에서 임의 요소 반환하는 매서드는 findAny.

- findAny 메서드를 다른 스트렘 연산과 연결해서 사용 가능.


Optional이란?

- 값의 존재나 부재 여부를 표현하는 컨테이너 클래스.

- fnidAny는 아무 요소도 반환하지 않을 수 있음.

- null은 쉽게 에러를 발생 시킬 수 있으므로 자바 8 라이브러리 설계자는 Optional<T> 기능 구현.


1) isPresent() - Optional이 값을 포함하는 true 반환. 포함하지 않으면 false 반환.

2) ifPresnet(Consumer<T> block) - 값이 있으면 주어진 블록 실행. T 형식의 인수를 받으며 void를 반환하는 람다 전달 가능.

3) T get() - 값이 존재하면 값 반환. 값이 없으면 NoSuchElementException 발생.

4) T orElse(T Other) - 값이 있으면 값 반환. 값이 없으면 기본값 반환.


3.4 첫번째 요소 찾기

- 리스트 또는 정렬된 연속 데이터로부터 생성된 스트림처럼 일부 스트림에는 논리적 아이템 순서가 정해져있을 수 있음.

- 이런 스트림의 첫 번재 요소를 찾는 findFirst 메서드 제공.


4. 리듀싱

- 모든 스트림 요소를 처리해 값으로 도출하는 질의를 리듀싱 연산이라 함.

- 함수형 프로그래밍 언어 용어로는 이 과정이 마치 종이를 작은 조각이 될 때까지 반복해서 접는 것과 비슷하다는 의미로 폴드(fold)라 부름.


표 5-1 작성.


5. 실전 예제

- 추가 포스팅에서 예제 제공.


6. 숫자형 스트림

- 숫자 스트림을 효율적으로 처리할 수 있도록 스트림 API는 기본형 특화 스트림 제공.


6.1 기본형 특화 스트림

- 박싱 비용을 피할 수 있도록 'int', 'double', 'long' 요소에 특화된 스트림 제공

> IntStream, DoubleStream, LongStream

- 각각의 인터페이스는 숫자 스트림의 합계를 계산할 수 있는 sum, 최댓값 요소를 검색하는 max등 자주 사용하는 숫자 관련 리듀싱 연산 수행 메서드 제공.

- 필요할 때 다시 객체 스트림으로 복원하는 기능도 제공.

- 특화 스트림은 오직 박싱과정에서 일어나는 효율성과 관련 있으며 스트림에 추가 기능을 제공하지 않음.

- boxed()를 통해 특화 스트림을 일반 스트림으로 변환 가능.

- Optional -> OptionalInt, OptionalDouble, OpionalLong 특화 스트림 버전 제공.


6.2 숫자 범위

- IntStream, LongStream에 range와 rangeClosed 두 가지 정적 메서드 제공.


7. 스트림 만들기

- stream 메서드로 컬렉션에서 스트림 획득 가능.


7.1 값으로 스트림 만들기

- 임의의 수를 인수로 받는 정적 메서드 Stream.of를 이용해 스트림 생성 가능.


7.2 배열로 스트림 만들기

- 배열을 인수로 받는 정적 메서드 Arrays.stream을 이용해 스트림 생성 가능.


7.3 파일로 스트림 만들기

- java.nio.file.Files의 많은 정적 메서드가 스트림을 반환.


7.4 함수로 무한 스트림 만들기

- 함수에서 스트림을 만들 수 있는 두 개의 정적 메서드 Stream.iterate와 Stream.generate 제공.

- iterate와 generate에서 만든 스트림은 요청할 때 마다 주어진 함수를 이용해 값을 생성.

> 따라서 무제한으로 값 계산 가능.

- iterate

> 초깃값과 람다를 신수로 받아 새로운 값을 끊임없이 생산 가능.

> 요청할 떄 마다 값을 생산 할 수 있으며 무한 스트림 생성 가능.

* 이러한 스트림을 언바운드 스트림이라 표현.

> 일반적으로 연속된 일련의 값을 만들때 iterate 사용.

- generate

> 요구할 떄 값을 계산하는 무한 스트림 생성 가능.

> iterate와 달리 생산된 각 값을 연속적으로 계산하지 않음.

> Supplier<T>를 인수로 받아 새로운 값을 생산.


8. 요약

- 복잡한 데이터 처리 질의 표현 가능.

- filter, distinct, skip, limit 메서드로 스트림을 필터링 하거나 자르기 가능.

- map, flatMap 메서드로 스트림 요소를 추출하거나 변환 가능.

- findFirst, findAny 메서드로 스트림의 요소 검색 가능.

- allMatch, noneMatcj, anyMatch 메서드를 이용해서 주어진 프레디케이트와 일치하는 요소를 스트림에서 검색 가능.

> 이들 메서드를 쇼트서킷, 즉 결과를 찾는 즉시 반환, 전체 스트림을 처리하지 않음.

- reduce 메서드로 스트림의 모든 요소를 반복 조합하며 값 도출 가능.

- filter, map등은 상태를 지정하지 않는 상태없는 연산.

- reduce 같은 연산은 계산하는데 필요한 상태 저장.

- sorted, distinct 등의 메서드는 새로운 스트림을 반환하기에 앞서 스트림의 모든 요소를 버퍼에 저장.

> 이런 메서드를 상태 있는 연산이라 부름.

- IntStream, DoubleStram, LongStream은 기본형 특화 스트림.

> 이들 연산은 기본형에 맞게 특화.

- 컬렉션뿐 아니라 값, 배열, 파일, iterate, generate 같은 메서드로도 스트림 생성 가능.

- 크기가 정해지지 않은 스트림을 무한 스트림이라 함.

'Java8 > Java 8 in Action' 카테고리의 다른 글

스트림으로 데이터 수집  (0) 2017.06.29
스트림 활용 예제 소스  (0) 2017.06.26
스트림 소개  (0) 2017.06.16
람다 표현식  (0) 2017.06.15
동작 파라미터화 예제 소스  (0) 2017.06.13

+ Recent posts