본문 바로가기
Rx

리액티브연산자 -6(데이터 쿼리하기,map,filter,reduce 함수)

by 봄석 2018. 12. 24.

본 내용은 필자가 학습한 내용을 정리하는 내용입니다.

대부분 의 내용이 아래 책의 내용이므로 원서를 구매해서 직접보시는걸 추천드립니다!

RxJava 프로그래밍 리액티브 프로그래밍 기초부터 RxAndroid까지 한 번에

유동환 , 박정준 지음 | 한빛미디어 | 2017년 09월 04일 출간

http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788968488658&orderClick=LAV&Kc=


저자님의 블로그

https://brunch.co.kr/@yudong#info




map(), filter(), reduce() 함수를 이용하여 데이터 쿼리하기

map() ,filter(), reduce() 함수를 이용하여 간단한 데이터 쿼리 예제를 해보겠습니다.

가상의 상점에서 발생한 오늘 매출은 다음과 같습니다.

- TV : $2,500

- Camera : $300

- TV : $1,600

- Phone : $800


예제코드는 오늘 발생한 TV 매출의 총합을 계산합니다.

1) 전체 매출 데이터를 입력함

2) 매출 데이터중 TV 매출을 필터링함

3) TV 매출의 합을 구함



예제


import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import io.reactivex.Maybe;
import io.reactivex.Observable;
 
 
 
public class QueryTvSales {
    
    public static void main(String args[]){
        //1. 데이터 입력
                List<Pair<String,Integer>> sales =new ArrayList<>();
                
                sales.add(Pair.of("TV",2500));
                sales.add(Pair.of("Camera",300));
                sales.add(Pair.of("TV",1600));
                sales.add(Pair.of("Phone",800));
                
                Maybe<Integer> tvSales =Observable.fromIterable(sales)
                        //2. 매출 데이터 중 TV 매출을 필터링 함
                        .filter(sale->"TV".equals(sale.getLeft()))
                        .map(sale->sale.getRight())
                //3. TV 매출의 합을 구함
                .reduce((sale1,sale2)->sale1+sale2);
                tvSales.subscribe(tot->System.out.println("TV Sale : $"+tot));
    }
}


일반적인 자바코드와 다른점 

첫번째 사용자 정의 클래스가 보이지 않습니다.

일반적인 객체지향 프로그램이라면 ("TV",2500) 이라는 데이터가 있는경우 새로운 클래스를 정의합니다

String 상품이름 ,int 가격

그리고 getter(),setter() 가 들어가게 됩니다


앞과 같은 클래스를  쓰지않기위해, 함수형 프로그래밍 에서는 일종의 자료구조인 클래스를 새로 만들기 보다 Pair 혹은 Tuple 같은 좀더 일반화된 자료 구조를 좀 더 선호합니다.

그러면 기존에 만들어진 함수를 활용하는 폭이 좀 더 넓어지기 때문입니다.


위 예제에서는 아파치 커먼즈의 Lang 3 라이브러리에서 제공하는 Pair<T,U> 객체가 쓰였습니다.



아파치 커먼즈의 Lang 3 라이브러리 추가하는 방법

//build.gradle 파일의 dependencies 에 다음코드를 추가합니다.

implementation 'org.apache.commons:commons-lang3:3.1'


예제설명

가장먼저 Pair<String,Integer> 타입의 List를 정의합니다.

각각 TV,Camera,Phone 제품의 매출액을 Pair.of() 라는 정적 팩토리 함수를 호출하여 List객체에 추가합니다.


TV 매출액은 int 타입이므로 Maybe<Integer>로 정의합니다. 

Observable이 아니라 Maybe 클래스를 사용하는 이유는 결과를 계산하기 위해 reduce()함수를 호출하기 때문입니다.


제품별 매출 중에서 TV의 매출을 취합하기 위해서는 filter() 함수를 활용합니다.

sales 변수의 왼쪽 값 (Pair 클래스에서 왼쪽 값을 얻어오기위해 getLeft() 함수를 활용합니다.

filter()를 거친 후에는 제품 이름이 더이상 필요하지 않으므로 getRight() 메서드를 호출합니다.)


각 TV 매출의 합계를 구하기 위해서는 map() 함수와 reduce() 함수를 활용합니다.

filter()를 거친 후에는 제품 이름이 더 필요하지 않으므로 map() 함수를 호출하여 Pair 객체의 오른쪽에 있는 매출액만 매핑합니다.


마지막으로 발생하는 매출액을 모두 더해주면 됩니다. reduce() 함수는 BiFunction 객체를 인자로 받기 때문에 람다 표현식을 사용할 대도 (sale1,sale2)와 같이 괄호로 묶어주어야 합니다.


실제 결과 계산은 subscribe() 함수를 호출하면 시작됩니다.

댓글