Reactive Programing

FlatMap 파헤치기

태인킴 2021. 2. 2. 23:47
반응형


1. flatMap

flatMap() 함수는 map()함수를 좀 더 발전시킨 함수 입니다. map() 함수는 원하는 입력값을 어떤 함수에 넣어서 변환할 수 있는 일대일 함수 입니다. 하지만, flatMap() 함수 똑같이 함수에 넣더라도 결과가 Observable로 나온다는 것이 다릅니다. 즉 map() 함수가 일대일 함수라면 flatMap() 함수는 일대다(Observable) 함수입니다.

마블다이어그램을 보시면, [빨간색](원) 1개를 입력하면, [빨간색](다이아몬드) 2개가 출력 됩니다. 결과값이 Observable 이므로 여러 개의 데이터를 발행할 수 있습니다. 마블다이어그램을 보시면, 무조건 2개의 데이터를 발행 하는 것 처럼 보이지만 입력 데이터의 속성에 따라서 1개를 발행할 수도 있고, 여러개를 발행할 수도 있습니다. 결과가 Observable이기 때문입니다. 

 

fun flatMapTest1() {
    val getDoubleDiamonds = { ball: String ->
        Observable.just("${ball}🔶", "${ball}🔶")
    }

    Observable.fromArray("1", "3", "5")
        .flatMap(getDoubleDiamonds)
        .subscribe{ str ->
            println(str)
        }
}

출력 결과

flatMap의 마블다이어그램을 그대로, 위 코드로 작성하였습니다. 

 

 

2. flatMap을 이용하여 구구단 만들기

fun gugudan() {
    Scanner(System.`in`)
        .nextInt()
        .also { println("$it 단") }
        .run {
            for (row in 0..9) {
                println("$this * $row = ${this * row}")
            }
        }
}

출력 결과

위와 같은 RxJava를 전혀 사용하지 않은 구구단을 구현한 코틀린 코드가 있습니다. 이것을 RxJava의 flatMap()을 사용해서 구구단을 구현해 보겠습니다.

 

 

3. 구구단 구현하기1

fun gugudan1() {
    val input = Scanner(System.`in`)
        .nextInt()
        .also { println("$it 단") }

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

    Observable.just(input)
        .flatMap (gugudan)
        .subscribe { println(it) }
}

먼저, Observable.range() 함수를 이용해서 1부터 9까지의 데이터를 만들고, map() 함수를 이용하여, (Int) -> Observable<String>인 함수를 gugudan 이라는 이름으로 구현 하였습니다. 반환값이 Observable<String> 이므로 flatMap의 인자로 사용하여 데이터를 발행할수 있습니다.

 

 

4. 구구단 구현하기2

fun gugudan2() {
    val input = Scanner(System.`in`)
        .nextInt()
        .also { println("$it 단") }

    Observable.just(input)
        .flatMap { input: Int ->
            Observable.range(1, 9)
                .map { row ->
                    "$row * $input = ${row * input}"
                }
        }.subscribe({
            println(it)
        }, {
            println(it.message)
        })
}

이번에는, [구구단 구현하기1]에서 gugudan 변수를 inline으로 flatMap의 넣어 구현 하였습니다. 출력값은 [구구단 구현하기1]과 같습니다.

 

 

5. 구구단 구현하기3

fun gugudan3() {
    val input = Scanner(System.`in`)
        .nextInt()
        .also { println("$it 단") }

    Observable.just(input)
        .flatMap (
            { _ -> Observable.range(1, 9)},
            { input, row -> "$input * $row = ${input * row}"}
        ).subscribe({
            println(it)
        }, {
            println(it.message)
        })
}

이번에도 출력 결과는 위와 같습니다. 하지만, 이번에는 flatMap의 인자로(Function, BiFunction)을 가지는 flatMap을 이용하여, 구현 하였습니다.

 

 

6. 정리하기

- Observable<R> flatMap(Function<T, R>)

- Observable<R> flatMap(Function<T, U>, BiFunction<T, U, R>)

- flatMap은 Observable을 반환값으로 가집니다.

- RxJava에서 Observable은 여러개의 데이터를 발행한다는 뜻 입니다.

반응형