본문 바로가기
코딩

2022.02.25_15일차_스트림

by 흥뷰자 2022. 3. 1.

15일차 학습내용

1. 스트림  
2. 스트림의 종류 
3. 스트림 파이프라인 
4. 필터링 distinct(), filter()  
5. 매핑 flapMappXXX(), mapXXX(), asXXXStream(), boxed()
6. 정렬 sorted() 
7. 루프 peek(), forEach() 
8. 매칭 allMatch(), anyMatch(), noteMatch() 모두 최종~~~ boolean타입리턴.
9. 기본 집계 sum(), count(), average(), max(), min() 
10. 커스텀 집계 reduce()  
11. 수집 collect() 
12. enum 열거형 



1. 스트림  


자바8부터 추가된 컬렉션의 저장요소를 하나씩 참조해서 
람다식으로 처리할 수 있도록 해주는 '반복자'이다.

1) 반복자 스트림
자바7 이전까지는 Iterator 반복자 

사용방법 stream()메서드로 반복자 얻어오기 vs Iterator()반복자 얻어오기 StreamEx01



2) 스트림 특징  vs Iterator

요약
Stream은 Iterator와 비슷한 역할을 하는 반복자이지만,
람다식으로 요소 처리 코드를 제공하는 점과, (코드짧다)
내부 반복자를 사용하므로 병렬처리가 쉽다는 점, (while같은거안쓴다)
//(서브작업 분리스레드 동시다발 연산, 속도 빠름 최고값, 누적합계 내부구현)
중간처리와 최종 처리 작업을 수행하는 점에서 많은 차이를 가지고 있다.

 

람다식 코드 제공

외부반복자(external iterator)란 //for, while문... 
개발자가 코드로 직접 컬렉션의 요소를 반복해서 가져오는 코드 패턴을 말함.
반면에 내부반복자(internal iterator)는 컬렉션 내부에서 요소들을 반복시키고,
개발자는 요소당 처리해야할 코드만 제공하는 코드 패턴을 갖는다. 


스트림은 중간처리와 최종처리를 할 수 있다.
중간처리에서는 매핑, 필터링, 정렬을 수행하고
최종처리에서는 반복, 카운팅, 평균, 총합 등 집계처리를 수행한다. <Stream02.png




쓰는 게 몇개 안되는 뻔한것들.. 익히면된다. 

 


2. 스트림의 종류  


스트림 객체를 얻을 수 있는 메서드들


java.util.steram 패키지에 Stream API들이 들어있다. 
(패키지 내부 상속구조)
BaseStream
- Stream (객체처리시. 기본형은 아래)
- DoubleStream
- IntStream
- LongStream

스트림을 얻을 수 있는 메서드들 
이미 만들어져 있는 메서드로 스트림을 얻어와용. 용도에 따라 맞는 스트림으로~

1) 컬렉션으로부터 스트림 얻어오기 #1에서 해본것.
컬렉션변수.stream()
계속 쓸 거 클래스 따로 만들기 메인메서드 없음.

StreamEx03

2) 배열로부터 스트림 얻기 : 리스트와 달리 String[] strArr = { , , } 배열은 스트림을 가져올수 없어서
Array.stream(타입) 에 담아주면 스트림으로 가져올 수있다.


3) 숫자 범위로부터 스트림 얻기  
IntStream.range(int start, int endExclusive)
IntStream.rangeClosed(int start, int endInclusive)



4) 파일경로가져오기 디렉토리
pass...



3. 스트림 파이프라인 


다량의 데이터를 가공해서 축소하는 것을 일반적으로 리덕션이라고 하는데,
데이터의 합계, 평균, 카운팅, 최대값, 최소값 등
대표적인 리덕션의 결과물이라고 볼 수 있다.
컬렉션의 요소를 리덕션의 결과물로 바로 집계할 수 없을 경우
필터링, 매핑, 정렬, 그루핑등, 중간 처리가 필요하다.

중간처리와 최종처리를 파이프라인으로 해결한다.
파이프라인은 여러개의 스트림이 연결되어있는 구조를 말한다.


Member 부품클래스, Stream04
상수의 사용법
파이프라인 만들어보기 (남자나이평균)

한줄로 깔끔하게. 이때는 최종적으로 걸러지는 데이터타입만 지정해주면되네


stream_05.png 중건처리메서드들...메서드에 뒤 이름이 stream으로 끝나는 것들~~~메소드는 필터나 매핑
리턴타입이 보통 optionalXXX 최종처리~~~~~~~~ 메소드가 xxMatch, 집계함수, forEach,collect() 들.. 그 나머지가 중간

 



4. 필터링메서드 distinct(), filter()  


중간처리 기능으로 요소를 걸러내는 역할

distinct() : 중복제거
filter(Predicate/InPredicate/Long../Double...) : 조건 필터링 변수 -> {true/false로 리턴} predicate타입이니까
//필터가 (predicate)매개변수 타입이 다양한것으로 오버로딩되어있음. 조건을 predicate에 줌

결과




5. 매핑메서드 flapMappXXX(), mapXXX(), asXXXStream(), boxed() 


중간처리 기능으로 스트림의 요소를 다른 요소로 대체하는 작업을 함.

<stream_05.png

1) flapMappXXX()
요소를 대체해주는 여러개의 요소들로 구성된 새로운 스트림을 리턴함. (Function타입)

2) mapXXX()
요소를 대체해주는 요소로 구성된 새로운 스트림을 리턴함.

 

1) 플랩맵 : 공백이나 쩜으로 표시된거 다른글자로 대체한 스트림

결과

결과

10

20

30

...

60

2) 그냥맵 : 키 밸류로 구성된것에서 보통쓰이나봉가, 아까 남자평균나이구하기에서 했음. getAge()


3) asXXXStream()
asDoubleStream() : IntStream의 int, LongStream의 long요소를 double로 변환해 DoubleStream으로 생성해줌
asLongStream() : IntStream의 int를 long으로 변환해 LongStream으로 생성
boxed() : int, long, double (기본형들)을 wrapper클래스 요소로 박싱해서 클래스의내부메서드를 사용해서 Stream으로 생성  ///박싱 언박싱 했었지.





6. 정렬 sorted()  메서드


중간단계에서 요소 정렬 필요할 때 사용. 최종 처리 전. 
실제 요소가 객체인 경우에는 Comparable(인터페이스)을 구현하지 않은 객체일 때 정렬하면 예외발생 : ClassCastException (다형성에서 형변환해야 비교가능하니까)
sorted()는 Comparable을 구현하고 사용 (객체클래스 implements Comparable<Strudent>붙여서/ 추상메서드 오버라이딩까지 해야 구현한거 , 이부분에서 리턴값으로 비교대상을 적어줌)

결과값

소트는 디폴트가 오름차순인데 

Comparable구현했기 때문에 내림차순 메서드 사용가능 comparator<T>.reverseOrder()

(객체에만 적용되는 메서드임. 위 int에서는 불가능 / 숫자도 적용하고 싶다면 배열로 아니고 Integer타입으로 변형 해야)
Student implements Comparable<Student> 추가작성

문자열정렬의경우 위 compareTo구현부를 다르게 구현~~~~

return name.compareTo(o.name); 




7. 루프 peek(), forEach() 



루핑은 요소 전체를 반복하는 것. 두개 비교

peek()  : 중간처리 메서드(파이프 라인에서) 최종처리 따로 안해주면 종료가 안됨~  루프로 중간확인해서, 최종sum을구하든지..
forEach() : 최종처리 메서드/ 중간에서 쓸 수 없음./ 뒤에 또 최종처리가 붙을수도 없어용






8. 매칭 allMatch(), anyMatch(), noteMatch() 모두 최종~~~ boolean타입리턴. 



최종 처리 단계에서 요소들이 특정 조건에 만족하는지 조사할 수 있도록
세 가지 매칭 메서드를 제공한다.

(조건)도 predicate frue/false나올수있게 넣어줘야..

Stream10



9. 기본 집계 sum(), count(), average(), max(), min()  

집계니까 문제는안되고 숫자로만하지
집계는  최종처리 기능, 처리한 후 하나의 값으로 산출해줌
 //리덕션 여러개 데이터 하나로 압축...




기본적으로 제공하는 집계들이다. count(), findFirst(), max(), min(), average(), reduce(), sum() 위에 표에있음..
이거말고 optional class
1) Optional 클래스로 리턴하면 매서드가 더 있다.  


단순히 집계값만 저장하는 것이 아니라,
집계값이 존재하지 않을 경우 디폴트 값을 설정할 수도 있고,
집계값을 처리하는 Consumer도 지정할 수 있어용 (있으면 이거처리해라~)
근데 그 하부메서드 사용시 요소없음에러발생하니까 처리해야함



10. 커스텀 집계 reduce()  < stream06.png 1:16


<stream14.png 매개변수 조금씩 다름...  오퍼레이터 말고 값을 하나 더 넣는것들이 있음. 값없으면 디폴트가 매개변수가되겠다, 스트림에 아무것도 없으면 디폴트로 써라~~

기본 집계이외에, 커드텀으로 다양한 집계 결과물을 만들 수 있도록 제공해주는 reduce의 메서드들(reduce에 오버로딩되어있는것들)

sum1. mapToInt는 자동으로 int합계를 내도록 만들어져있음

 

sum2. map은 int가 지정되어있지 않았음에도, 내부적으로 연산처리는 되지만  get()을 하지 않으면 리턴타입이 optional-Integer로 오브젝트로 처리한거라 그렇게 변수타입을 지정하든지 , optional뒤에 어떤거로 가져올지 Integer객체로 주는 get()을 붙여준다

그래서 가급적이면 타입까지 상세하게 쓰라는것. 코드 간결해짐.

 

sum3. default값을 넣어준형태



11. 수집 collect()  



Stream은 요소들을 필터링 또는 매핑한 후 요소들을 수집하는 최종 처리 메서드인 
collect()를 제공한다. 최종처리로 반복을 돌리거나 집계하는거 말고 그냥 결과데이터 취합해서 가져와라~~~~
필요한 요소만 컬렉션으로 담을 수 있고, 요소들을 그루핑한 후 집계처리(reduction)할 수 있다.

1)필터링한 요소 수집 / 2) 사용자 정의 컨테이너에 수집 / 3) 그루핑해서 수집 / 4) 그루핑 후 매핑 및 집계



1) 필터링한 요소 수집 


R Collect(Collector<T,A,R> collector) 메서드는 //T타입 요소하나를 Accumalator누적기가 Return타입으로 저장
필터링 또는 매핑된 새로운 컬렉션에 수집하고, 이 컬렉션을 리턴

Collector의 구현객체는 Collectors 클래스의 클래스메서드(static)를 이용하여 얻을 수 있다.  <stream_15.png

toList()와 Key,Value형태의 toMap() 많이씀/ 중복되는없애야하면 toSet()


<Person단일클래스 (메인없는) 



12. enum 열거형 


서로 연관성 있는 상수들의 집합. public satatic final int ....

- 열거체를 비교할 때 실제 값뿐만 아니라 타입까지도 체크 (안전성 보장)
- 열거체의 상수값이 재정의되어도 다시 컴파일할 필요 없음.

-1. 열거형 정의하기
enum 열거형이름 {상수명, 상수명, ...}  
0,     1,     2...   // 대문자로 써서 일반변수 아닌걸 표시해주는게 좋다. 상수명이 자동으로 0,1,2 번호값을 부여받아용~~ 실제 사용은 이름만 가지고 쓰면돼. p.상수명? //{} 뒤에 세미콜론이 없어용
enum 열거형이름 {상수명(0), 상수명10), ...}//// 상수값을 직접 지정도 가능  

int 열거형이름.상수명;

처리 스트림으로






열거형 상수간의 비교 :== 로 비교, << 연산자호출하지 않아서 속도가 빨라~~
compareTo() 가능 : 같으면 0, 왼쪽크면 양수, 오른쪽 크면 음수
<> 사용불가

int [] arr = 




2) 사용자 정의 컨테이너에 수집

list, set, map 등 기본제공해주는 자료구조 컬렉션이 아닌 사용자가 정의한 컨테이너 객체에 수집하는 방법
내가 구현해서 쓸수있게 메서드 컬렉트로 주고있다 (매개변수가세개인 collect)

supplier 요소들이수집될 컨테이너객체를생성해줌. 최종공급자를 객체생성 (리턴만해주는게 supplier)

consumer R요소 객체 T로수집 (던져주는거 그냥 소비하는애)

biconsumer 컨테이너객체로 결합해줌

 

학생중 여학생만 수집하는 컨테이너

 

두개의 리스트를 합치려면 getList로 하나씩 addAll해야함. 

큰 대형프로젝트에서나 커스텀으로 만들지...



3) 그루핑해서 수집


collect() 호출 시 collectors의 groupingBy() / groupingByConcurrent()로 받은
Collector를 매개값으로 대입하면 그루핑 가능.
그루핑바이는 스레드가 안전하지 않은 맵을 사용하고(동기화가안되는 맵타입)/ 컨커런트는 스레드를 안전하게 맵을 쓸수있는 componentMap을생성해준다 

사람생성해놓고 그룹에 담아서 Array.asList()

Collectors.groupingBy(입력출력갑있는 <T주면 K벨류> classifier도 미리 만들어놔,분류할기준getGender()

스트림아~형식맞춰담아놓은거 잘옮겨줘 




4) 그루핑 후 매핑 및 집계

그룹 바이를 하면 매핑이나 집계를 할 수있도록, 두번 째 매개값으로 컬렉터를 가질 수 있다.

 



'코딩' 카테고리의 다른 글

2022.03.01_17일차_css(1)  (0) 2022.03.04
2022.02.28_16일차_html, 태그별 속성  (0) 2022.03.02
2022.02.24_14일차_람다식  (0) 2022.02.28
2022.02.23_13일차  (0) 2022.02.27
2022.02.22_12일차_컬렉션  (0) 2022.02.26

댓글