[RxJava] RxJava 변환 연산자

minnie_dev·2022년 2월 18일
0

RxJava

목록 보기
4/8
post-thumbnail

📝RxJava의 학습 순서
1. Observable 클래스를 명확하게 이해(특히 Hot Observable과 Cold Observable의 개념을 꼭 이해해야함)
2. 변환, 제어, 결합 연산자 등 카테고리별 주요 함수 공부
3. 스케줄러의 의미, subscribeOn()과 observeOn()함수의 차이
4. 그 밖의 디버깅, 흐름 제어함수


1. RxJava 연산자

RxJava 연산자(Operators)의 종류는 아래의 표로 정리하였다.

연산자 종류정의
생성연산자Observable, Single 클래스 등을 이용하여 데이터의 흐름을 만들어내는 함수create(),just(),fromXXX(),interval(),
range(),timer() 등
변환연산자입력을 받아서 원하는 출력을 내는 전통적인 의미의 함수map(),flatmap(), reduce() 등
제어연산자입력 데이터 중 원하는 데이터를 골라내는 함수filter(),first(),take() 등
결합연산자두 개 이상의 입력된 데이터를 하나의 데이터로 통합하는 연산자zip(), combinelLatest(), Merge(),concat()
오류처리연산자연산자 내에서 예외 처리 구현을 위한 함수onErrorReturn(), onErrorResumeNext(), retry() 등
조건연산자Observable의 흐름을 제어하는역할amb(),takeUntil(),skipUtil(),all() 등

수학과 집합형 연산자    
수학 함수와 연관있는 연산자sum() 등
기타연산자구독,발행 등의 이벤트 처리 및 데이터의 숫자를 세는 특징별 연산자subscribeOn(), observeOn(),count() 등

생성 연산자는 Observable 설명과 함께 작성하였으므로 변환 연산자

2. RxJava 변환 연산자

RxJava의 변환 연산자란 입력을 받아서 원하는 출력을 내는 의미의 함수로 만들어진 데이터 흐름을 원하는 대로 변형 시킬 수 있다.
ex) map(), flatmap(), cancatMap(), switchMap(), reduce(), scan()

2-1. map

map은 기본적인 데이터 변환으로 입력값을 어떤 함수에 넣어서 원하는 값으로 변환하는 함수이다. 데이터를 데이터로 변환시키는 함수로 데이터 한 개를 변환하여 데이터 한 개가 나온다.

코드를 보면 numArr변수는 String 배열 객체이고, 이 변수를 이용해 데이터 흐름을 생성하기 때문에 초기 데이터들은 String타입의 데이터들이다.

String[] numArr = new String[]{"1","2","3"};
Observable.fromArray(numArr)
          .map(Integer::parseInt)
          .subscribe(System.out::println);
위 코드가 출력된 내용
1
2
3

String형이였던 데이터들이 Int형인 데이터로 출력되는 것을 확인할수 있다.

2-2. flatMap

flatMap단일 데이터를 또 다른 데이터 흐름으로 변환하는 함수이다. 여기서 또 다른 데이터 흐름이란 Observable을 의미한다.
연산 결과가 반드시 Observable로 나온다는 것이 map과 다른 점이다. map함수는 1:1 데이터 연산 함수라면 flatMap은 1:N, 1:1 Observable함수이다.
map은 동기 방식이기 때문에 비동기와 같이 사용할 경우 그 효과를 보기 어려우며 비동기 작업으로 데이터를 처리하고자 하는 경우 map이 아닌 flatMap을 사용해야 한다.

Observable.interval(100L, TimeUnit.MILLISECONDS)
          .take(3)
          .flatMap(data -> Observable.interval(200L, TimeUnit.MILLISECONDS)
                        .take(2)
                        .map(val -> "data: " + data + " value: " + val))
          .subscribe(System.out::println);
위 코드가 출력된 내용
data: 0 value: 0
data: 1 value: 0
data: 2 value: 0
data: 0 value: 1
data: 1 value: 1
data: 2 value: 1

map과 flatMap의 차이를 정리해보면 map은 1개의 데이터를 다른 값이나 타입으로 변환해주는 것이고 flatMap은 1개의 값을 받아 여러 개의 데이터(Observable)로 확장해주는 것이다.

2-3. concatMap

concatMap은 flatMap과 사용법이 완전 똑같다. 다른 점은 flatMap과 달리 입력 데이터의 순서를 보장해준다는 것이다. 대신 입력 순서를 보장해주는만큼 데이터 간 기다리는 지연 시간이 생기기 때문에 총 실행 시간이 길어진다.

Observable.interval(100L, TimeUnit.MILLISECONDS)
                .take(3)
                .concatMap(data -> Observable.interval(200L, TimeUnit.MILLISECONDS)
                        .take(2)
                        .map(val -> "data: " + data + " value: " + val))
                .subscribe(System.out::println);
위 코드가 출력된 내용
data: 0 value: 0
data: 0 value: 1
data: 1 value: 0
data: 1 value: 1
data: 2 value: 0
data: 2 value: 1

2-4. switchMap

switchMap은 가장 최신 데이터를 보장하며 데이터 흐름을 생성한다.
flatMap과 concatMap과 동일하게 모든 데이터 입력이 들어오면 새로운 데이터 흐름으로 변환하려고 시도한다. 그런데 변환 작업 중 새로운 데이터 입력이 들어오게 되면 기존 작업을 취소하고 새로운 데이터에 대해서 변환 작업을 진행한다. 변환 도중 새로운 입력이 들어오게 되어 기존 작업을 취소하게 되고 최종적으로 마지막 입력 데이터에 대해서 변환을 진행한다. 이러한 특성은 실시간으로 최신 데이터를 가져올 때 유용하게 쓰인다.

Observable.interval(100L, TimeUnit.MILLISECONDS)
          .take(3)
          .switchMap(data -> Observable.interval(200L, TimeUnit.MILLISECONDS)
                					   .take(2)
                		               .map(val -> "data: " + data + " value: " + val))
          .subscribe(System.out::println);
위 코드가 출력된 내용
data: 2 value: 0
data: 2 value: 1

2-5. reduce

reduce는 모든 데이터를 조합(변환)하여 최종 값을 출력한다. 데이터를 중첩되게 변환시켜 최종적인 새로운 변환된 단일 데이터를 만든다.

String[] balls = new String[] {"A", "B", "C"};
 
Observable.fromArray(balls)
          .reduce((ball1, ball2) -> ball2 + "(" + ball1 + ")")
          .subscribe(System.out::println);
위 코드가 출력된 내용
C(B(A))

데이터로 변환된 값이 구독자에게 전달되는 것이 아닌 다시 reduce함수의 입력값으로 전달되어 새로운 변환된 데이터를 생성하고 다시 입력값으로 들어가는 이러한 과정이 데이터 흐름의 onComplete() 이벤트가 발생할 때까지 진행됩니다.

2-6. scan

scan모든 데이터를 조합(변환)하며 각 결과 값을 출력한다. 실행할 때마다 입력값에 맞는 중간 결과 및 최종 결과를 구독자에게 발행한다. reduce연산자와 비슷하나 다른 점은 reduce는 마지막 1개 scan은 중간 중간 결과까지 계속 발행하는 것이다.

String[] balls = new String[] {"A", "B", "C"};
 
Observable.fromArray(balls)
          .scan((ball1, ball2) -> ball2 + "(" + ball1 + ")")
          .subscribe(System.out::println);
위 코드가 출력된 내용
A
B(A)
C(B(A))

참고 : https://jaeryo2357.tistory.com/81
profile
Android Developer

0개의 댓글