티스토리 뷰

반응형

FlatMap

FlatMap 함수는 Map 함수를 발전시킨 함수이다. FlatMap 함수는 결과가 Observable로 나옵니다.

Map 함수가 일대일 함수라면 FlatMap 함수는 일대다 혹은 일대일 Observable 함수입니다.

 

 

 

  1. 빨간색 원을 넣으면 첫 번째 빨간색 다이아몬드, 두 번째 빨간색 다이아몬드가 나온다.
  2. 초록색 원을 넣으면 같은 방식으로 첫 번째 초록색 다이아몬드, 두 번째 초록색 다이아몬드가 나온다.

위와 같이 FlatMap 함수는 결과 값이 Observable이므로 여러 개의 데이터를 발행할 수 있습니다.

 

입력

import io.reactivex.Observable

class FlatMapExample {
    fun marbleDiagram() {
        val getDoubleDiamonds = Function<String, Observable<String>> { 
            ball -> Observable.just("$ball◇", "$ball◇") 
       }

        val balls = arrayOf("1", "3", "5")
        val source = Observable.fromArray(*balls)
            .flatMap(getDoubleDiamonds)
        source.subscribe { data -> println(data) }
    }
}

fun main() {
    val demo = FlatMapExample()
    demo.marbleDiagram()
}

 

출력

1◇
1◇
3◇
3◇
5◇
5◇

 

 

아래는 람다 표현 식으로 작성한 코드입니다.

 

입력

import io.reactivex.Observable

class FlatMapExample {fun flatMapLamda() {
        val balls = arrayOf("1", "3", "5")
        val source = Observable.fromArray(*balls)
            .flatMap { ball -> Observable.just("$ball◇", "$ball◇") }
        source.subscribe { data -> println(data) }
    }
}

fun main() {
    val demo = FlatMapExample()
    demo.flatMapLamda()
}

 

출력

1◇
1◇
3◇
3◇
5◇
5◇

 

 

구구단 예제

먼저 일반적인 구구단 예제입니다.

 

입력

import java.util.*

class Gugudan {
    fun plainKotlin() {
        val scanner = Scanner(System.`in`)
        print("Gugudan Input : ")
        val dan = scanner.nextInt()

        for (row in 1..9) println("$dan * $row = ${dan * row}")
        
        scanner.close()
    }
}

fun main() {
    val demo = Gugudan()
    demo.plainKotlin()
}

 

아래 코드는 for문을 Observable로 변환한 것입니다.

 

입력

import io.reactivex.Observable
import java.util.*

class Gugudan {
    fun reactiveV1() {
        val scanner = Scanner(System.`in`)
        print("Gugudan Input : ")
        val dan = scanner.nextInt()

        val source = Observable.range(1, 9)
        source.subscribe { row -> println("$dan * $row = ${dan * row}") }

        scanner.close()
    }
}

fun main() {
    val demo = Gugudan()
    demo.reactiveV1()
}

 

아래 코드는 flatMap 함수를 활용한 것입니다.

 

입력

import io.reactivex.Observable
import io.reactivex.functions.Function
import java.util.*

class Gugudan {
    val scanner = Scanner(System.`in`)
        print("Gugudan Input : ")
        val dan = scanner.nextInt()

        val gugudan = Function<Int, Observable<String>> { num ->
            Observable.range(1, 9)
                .map { row: Int -> "$num * $row = ${num * row}" }
        }

        val source = Observable.just(dan).flatMap(gugudan)
        source.subscribe { data -> println(data) }

        scanner.close()
    }
}

fun main() {
    val demo = Gugudan()
    demo.reactiveV2()
}

 

 

아래는 FlatMap 함수 안에 gugudan 함수를 넣은 코드입니다.

 

입력

import io.reactivex.Observable
import java.util.*

class Gugudan {
    fun reactiveV3() {
        val scanner = Scanner(System.`in`)
        print("Gugudan Input : ")
        val dan = scanner.nextInt()

        val source = Observable.just(dan)
            .flatMap { num -> Observable.range(1, 9) }
            .map { row -> println("$dan * $row = ${dan * row}") }

        source.subscribe()
        scanner.close()
    }
}

fun main() {
    val demo = Gugudan()
    demo.reactiveV3()
}

 

 

지금까지 호출한 FlatMap 함수의 원형은 아래와 같습니다.

@SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) {
        return flatMap(mapper, false);
    }

 

SchedulerSupport.NONE은 간단히 현재 스레드에서 실행한다고 보면 됩니다.

ObservableSource은 Observable처럼 데이터를 발행할 수 있는 개체를 포괄해서 지칭합니다.

Single 클래스에는 SingleSource라는 별도 인터페이스가 존재합니다.

 

 

 

아래는 FlatMap 함수의 원형과 조금 다른 형태인 resultSelector를 사용하도록 변경한 FlatMap 코드입니다.

 

입력

import io.reactivex.Observable
import java.util.*

class Gugudan {
    fun usingResultSelector() {
        val scanner = Scanner(System.`in`)
        print("Gugudan Input : ")
        val dan = scanner.nextInt()

        val source = Observable.just(dan)
            .flatMap({ gugu -> Observable.range(1, 9) }) { gugu, i ->
                "$gugu * $i = ${gugu * i}"
            }

        source.subscribe{ data -> println(data) }
    }
}

fun main() {
    val demo = Gugudan()
    demo.usingResultSelector()
}
반응형

'알려주는 이야기 > RxJava' 카테고리의 다른 글

12. RxJava - Reduce  (0) 2020.07.09
11. RxJava - Filter  (0) 2020.07.09
9. RxJava - Map  (0) 2020.07.09
8. RxJava - ConnectableObservable  (0) 2020.07.09
7. RxJava - Subject  (0) 2020.07.09
댓글