본문 바로가기
Rx

리액티브연산자 -1( map함수)

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=




map()함수란?

map()함수는 입력값을 어떤 함수에 넣어서 원하는 값으로 변환하는 함수입니다.(변환연산자 중)

String을 String 으로 변환할 수도 있고 String을 Integer나 다른 객체로 변환할 수도 있습니다.

지금까지의 객체 지향 프로그래밍과 다른 점은 '어떤 함수에 넣어서' 입니다.


map() 함수는 입력 데이터와 그것을 변환해줄 함수를 이어주는 중개업자가 있다고 생각하면 이해하기 쉽습니다. 


map() 함수의 마블다이어그램

위에 서 말했던 '어떤 함수'는 마블 다이어 그램의 map{} 사이에 있습니다.

원을 입력받아서 다이아몬드로 변환합니다.


위의 마블 다이어그램을 위의 시간선의 빨,노,초,연파,파,보라 를 1,2,3,4,5,6 이라 하고 

아래시간선의 다이아몬드를 1<>,2<>,3<>,4<>,5<>,6<> 이라고 표기하도록하겠습니다.


기존의 자바 메소드로 표현하면 아래와 같습니다.

public static String getDiamond(String ball){
        return ball+"<>";
}

하지만 이대로는 map()함수에 '넣어서' 사용할 수 없습니다. 자바는 메소드에 대한 포인터를 지원하지 않기 때문입니다. 함수를 인자로 넘길 수도 없습니다. 

따라서 RxJava를 사용해야합니다 .



마블다이어그램을 RxJava로 구현하면 아래 예와 같습니다

String[] balls = {"1","2","3","5"};
Observable<String> source=Observable.fromArray(balls).map(ball->ball+"<>");
source.subscribe(Log::i);


getDiamond() 메소드의 구현부가 map()함수의 인자로 들어가면서 ball-> ball+"<>"로 바뀌었습니다. 다른점은 자바8에 새로추가된 람다표현식으로 표현했다는 것입니다.

이 방법이 map()함수를  사용하는 가장 일반적인 방법입니다. 익명크래스를 넣지않고 람다 표현식으로 넣으면 코드가 간결해집니다.



map()함수의 원형은 아래와 같습니다.

@CheckReturnValue
@SchedulerSupport(value="none")
public final <R> OBservable<R> map(Function<? super T,? extends R> mapper)



@CheckReturnValue 는 반환 값을 확인한다는 의미 입니다. 대부분의 연산자에서 함께 사용합니다. @SchedulerSupport(value="none")는 스케줄러를 지원하지 않는다는 의미입니다. 

즉 현제 스레드에서 실행합니다.


map()함수의 인자는 아래와 같습니다.

Function<? super T,? extends R> mapper




RxJava의 람다표현식은 세가지 제네릭 함수현 인터페이스 중 하나로 나타냅니다. 이는 자바8과 동일한 인터페이스 입니다.


RxJava의 제네릭 함수형 인터페이스

 인터페이스 이름

포함 메소드 

설명 

 Predicate<T> 

 boolean test(T t) 


 t 값을 받아서 참이나 거짓을 반환합니다.

 

 Consumer<T>

 void accept(T t) 


 t 값을  받아서 처리합니다. 반환값은 없습 니다.


 Function<T,R> 

 R apply(T t)  


 t 값을 받아서 결과를 반환합니다.

 


Function 인터페이스는 제네릭 타입T를 인자로 전달받아 제네릭타입 R을 반환합니다. 위에 있는 mapper 변수도 T를 인자로 전달받아 R을 결과로 반환하는 Function 인터페이스 입니다.



아래 예는 마블 다이어그램 예제를 Function 인터페이스를 이용해 분리한 것입니다.

Function<String, String> getDiamond = ball -> ball+"<>";
String[] balls= {"1","2","3","5"};
Observable<String> source = Observable.fromArray(balls).map(getDiamond);
source.subscribe(Log::i);

map() 함수는 반드시 입력 타입과 반환타입이 같을 필요가 없습니다. String 객체를 입력으로 받아 Integer 객체를 반환해도 됩니다.




아래 예제는 색깔이 적힌 원(Ball)을 넣으면 적절한 숫자로 변환하는 예제입니다.

데이터 타입을 자동으로 변환하는데  타입변환을 명시하지 않았습니다. 컴파일러가 알아서 타입을 추론하기 떄문입니다.

Function<String,Integer> ballToIndex =ball -> {
            switch(ball){
            case "RED": return 1;
            case "YELLOW": return 2;
            case "GREEN": return 3;
            case "BLUE": return 5;
            default: return -1;
            }
};
        
String[] balls ={"RED","YELLOW","GREEN","BLUE"};
Observable<Integer> source= Observable.fromArray(balls).map(ballToIndex);//명시적 타입 변환 없이 바로 사용할 수 있음
source.subscribe(System.out::println);


Function 객체의 람다표현식이 앞과 좀 다른데, 앞에선 ball-> ball+"<>"로 간단하게 표현 했다면, 이번 예제의 람다 표현식 ballToIndex() 함수에서는 중괄호( {} )가 추가되었습니다.

원래 람다 표현식의 몸체는 중괄효 안에 있어야 하지만 문장이 1개라면 중괄호 ( {} )를 생략하여도 되기떄문에 앞에서는 생략한 것입니다.


아래는 실행결과 입니다.

1
2
3
5





정리하자면 

map() 함수는 내가 원하는 값을 '어떤 함수' (Function 인터페이스 객체나, 람다표현식) 에 넣는것입니다

댓글