연산자
map() 함수는 입력값을 어떤 함수에 넣어서 원하는 값으로 변환하는 함수.
ex) String을 String으로 변환 / String을 Integer나 다른 객체로 변환
>> map() 함수의 마블 다이어그램
>> map() 함수의 예시
public void marbleDiagram() {
String[] balls = {"1", "2", "3", "5"};
Observable<String> source = Observable.fromArray(balls)
.map(ball -> ball + "<>");
source.subscribe(System.out::println);
}
>>1<>
>>2<>
>>3<>
>>5<>
>> map() 함수의 Example Code
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
>> map() 함수의 원형
@CheckReturnValue
는 반환값을 확인한다는 의미입니다.@SchedulerSupport
는 스케줄러를 지원하지 않는다는 의미 → 현재 스레드에서 실행한다는 의미입니다.Function<? super T, ? extends R> mapper
>> map() 함수의 인자
Predicate<T> : t값을 받아서 참이나 거짓을 반환 ( boolean test(T t) )
Consumer<T> : t값을 받아서 처리하고 반환값은 없음 ( void accept(T t) )
Function<T, R> : t값을 받아서 결과 R 반환 ( R apply(T t) )
public void mapFunction() {
Function<String, String> getDiamond = ball -> ball + "<>";
String[] balls = {"1", "2", "3", "5"};
Observable<String> source = Observable.fromArray(balls).map(getDiamond);
source.subscribe(System.out::println);
}
>>1<>
>>2<>
>>3<>
>>5<>
>> 위 marbleDiagram() 예제를 Function 인터페이스를 이용해 분리
public void mappingType() {
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);
}
>>1
>>2
>>3
>>5
>> flatMap() 함수의 마블 다이어그램
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) {}
>> flatMap() 함수의 원형
@CheckReturnValue
는 반환값을 확인한다는 의미입니다.@SchedulerSupport
는 스케줄러를 지원하지 않는다는 의미 → 현재 스레드에서 실행한다는 의미입니다.public void marbleDiagram() {
Function<String, Observable<String>> getDoubleDiamonds =
ball -> Observable.just(ball + "<>", ball + "<>");
String[] balls = {"1", "3", "5"};
Observable<String> source = Observable.fromArray(balls)
.flatMap(getDoubleDiamonds);
//Observable<String> source = Observable.fromArray(balls)
// .flatMap(ball -> Observable.just(ball + "<>", ball + "<>");
source.subscribe(System.out::println);
}
>>1<>
>>1<>
>>3<>
>>3<>
>>5<>
>>5<>
>> Example Code
public void plainJava() {
Scanner in = new Scanner(System.in);
System.out.println("Gugudan Input : ");
int dan = Integer.parseInt(in.nextLine());
for(int row = 1; row <= 9; row++) {
System.out.println(dan + " * " + row + " = " + dan * row);
}
}
>>Gugudan Input : 7
>>7 * 1 = 7
>>7 * 2 = 14
>>7 * 3 = 21
>>7 * 4 = 28
>>7 * 5 = 35
>>7 * 6 = 42
>>7 * 7 = 49
>>7 * 8 = 56
>>7 * 9 = 63
>> Java코드로 작성한 구구단
public void reactiveV1() {
Scanner in = new Scanner(System.in);
System.out.println("Gugudan Input : ");
int dan = Integer.parseInt(in.nextLine());
Observable<Integer> source = Observable.range(1, 9);
source.subscribe(row -> System.out.println(dan + " * " + row + " = " + dan * row));
}
>>Gugudan Input : 7
>>7 * 1 = 7
>>7 * 2 = 14
>>7 * 3 = 21
>>7 * 4 = 28
>>7 * 5 = 35
>>7 * 6 = 42
>>7 * 7 = 49
>>7 * 8 = 56
>>7 * 9 = 63
>> for문 Observable 변환
public void reactiveV2() {
Scanner in = new Scanner(System.in);
System.out.println("Gugudan Input : ");
int dan = Integer.parseInt(in.nextLine());
Function<Integer, Observable<String>> gugudan = num ->
Observable.range(1, 9).map(row -> num + " * " + row + " = " + num * row);
Observable<String> source = Observable.just(dan).flatMap(gugudan);
source.subscribe(System.out::println);
}
>>Gugudan Input : 7
>>7 * 1 = 7
>>7 * 2 = 14
>>7 * 3 = 21
>>7 * 4 = 28
>>7 * 5 = 35
>>7 * 6 = 42
>>7 * 7 = 49
>>7 * 8 = 56
>>7 * 9 = 63
>> flatMap() 함수를 활용한 코드 변환
>> filter() 함수의 마블 다이어그램
>> filter() 함수의 예시
public void marbleDiagram() {
String[] objs = {"1 CIRCLE", "2 DIAMOND", "3 TRIANGLE", "4 DIAMOND", "5 CIRCLE", "6 HEXAGON"};
Observable<String> source = Observable.fromArray(objs).filter(obj -> obj.endsWith("CIRCLE"));
source.subscribe(System.out::println);
}
>>1 CIRCLE
>>5 CIRCLE
>> filter() 함수의 활용 예
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Observable<T> filter(Predicate<? super T> predicate) {}
>> filter() 함수의 원형
public void marbleDiagram() {
String[] objs = {"1 CIRCLE", "2 DIAMOND", "3 TRIANGLE", "4 DIAMOND", "5 CIRCLE", "6 HEXAGON"};
Predicate<String> filterCircle = obj -> obj.endsWith("CIRCLE");
Observable<String> source = Observable.fromArray(objs).filter(filterCircle);
source.subscribe(System.out::println);
}
>>1 CIRCLE
>>5 CIRCLE
filter() 함수와 비슷한 함수들
public void otherFilters() {
Integer[] numbers = {100, 200, 300, 400, 500};
Single<Integer> single;
Observable<Integer> source;
//1. first
single = Observable.fromArray(numbers).first(-1);
single.subscribe(data -> System.out.println("first() value = " + data));
//2. last
single = Observable.fromArray(numbers).last(999);
single.subscribe(data -> System.out.println("last() value = " + data));
//3. take(N)
source = Observable.fromArray(numbers).take(3);
source.subscribe(data -> System.out.println("take(3) values = " + data));
//4. takeLast(N)
source = Observable.fromArray(numbers).takeLast(3);
source.subscribe(data -> System.out.println("takeLast(3) values = " + data));
//5. skip(N)
source = Observable.fromArray(numbers).skip(2);
source.subscribe(data -> System.out.println("skip(2) values = " + data));
//6. skipLast(N)
source = Observable.fromArray(numbers).skipLast(2);
source.subscribe(data -> System.out.println("skipLast(2) values = " + data));
}
>>first() value = 100
>>last() value = 500
>>take(3) values = 100
>>take(3) values = 200
>>take(3) values = 300
>>takeLast(3) values = 300
>>takeLast(3) values = 400
>>takeLast(3) values = 500
>>skip(2) values = 300
>>skip(2) values = 400
>>skip(2) values = 500
>>skipLast(2) values = 100
>>skipLast(2) values = 200
>>skipLast(2) values = 300
>> filter() 함수와 비슷한 함수들의 활용 예
>> reduce() 함수의 마블 다이어그램
>> reduce() 함수의 예시
public void marbleDiagram() {
String[] balls = {"1", "3", "5"};
Maybe<String> source = Observable.fromArray(balls)
.reduce((ball1, ball2) -> ball2 + "(" + ball1 + ")");
source.subscribe(System.out::println);
}
>> 5(3(1))
>> reduce() 함수의 활용 예
Maybe 클래스
Single 클래스와 마찬가지로 최대 데이터 하나를 가질 수 있지만 데이터 발행 없이 바로 데이터 발생을 완료할 수도 있는 클래스.
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Maybe<T> reduce(BiFunction<T, T, T> reducer) {}
>> reduce() 함수의 원형
public void marbleDiagram() {
String[] balls = {"1", "3", "5"};
BiFunction<String, String, String> mergeBalls = (ball1, ball2) -> ball2 + "(" + ball1 + ")";
Maybe<String> source = Observable.fromArray(balls)
.reduce(mergeBalls);
source.subscribe(System.out::println);
}
>> 5(3(1))
>> reduce() 함수의 람다 표현식 분리
map(), filter(), reduce() 함수를 활용하여 간단한 데이터 쿼리 예제 만들기.
상점에서 발생한 오늘 매출
- TV : $2,500
- Camera : $300
- TV : $1,600
- Phone : $800
오늘 발생한 TV 매출의 총합은?
1. 전체 매출 데이터를 입력함.
2. 매출 데이터 중 TV 매출을 필터링함.
3. TV 매출의 합을 구함.
public void run() {
List<Pair<String, Integer>> sales = new ArrayList<>();
sales.add(Pair.create("TV", 2500));
sales.add(Pair.create("Camera", 300));
sales.add(Pair.create("TV", 1600));
sales.add(Pair.create("Phone", 800));
Maybe<Integer> tvSales = Observable.fromIterable(sales)
.filter(sale -> "TV".equals(sale.getKey()))
.map(sale -> sale.getValue())
.reduce((sale1, sale2) -> sale1 + sale2);
tvSales.subscribe(tot -> System.out.println("TV Sales : $" + tot));
}
>> TV Sales : $4100
>> TV 매출의 총합을 구하는 예제
TV의 매출액은 int 타입이므로 Maybe
Observable이 아니라 Maybe 클래스를 사용하는 이유는 결과 계산을 위한 reduce() 함수를 호출하기 위해서.