Android 공부/Coroutine

[XX캠퍼스] 09.Kotlin Coroutines & Flow ( Flow 연산)

Machine_웅 2022. 7. 26. 17:58
728x90
반응형

map

filter

filterNot

transform 

take 

takeWhile 

drop 

dropWhile 

종단 연산자(terminal operator)

- reduce

- fold 

count 연산자

 

 

 

 플로우와  map

플로우에서 map 연산을 통해 데이터를 가공할 수 있습니다.

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun flowSomething(): Flow<Int> = flow {
    repeat(10) {
        emit(Random.nextInt(0, 500))
        delay(10L)
    }
}

fun main() = runBlocking {
    flowSomething().map {
    	// it으로 활용 
        "$it $it"    // 같은 문자열 두번 print 되도록 함. 
    }.collect { value ->
        println(value)
    }
}

연산결과
129 129
204 204
352 352
299 299
130 130
213 213

플로우와 filter

filter 기능을 이용해 짝수만 남겨봅시다.

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking<Unit> {
    (1..20).asFlow().filter { 
        // 조건에 맞는 데이터만 남긴다 
        (it % 2) == 0 // 조건 (술어, predicate ) 
        
    }.collect {
        println(it)
    }
}

 


filterNot

만약 홀수만 남기고 싶을 때 술어(predicate)를 수정할 수 도 있습니다.

하지만 술어를 그대로 두고 filterNot을 사용할 수도 있습니다.

 

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking<Unit> {
    (1..20).asFlow().filterNot {  // filter 와 차이 
        (it % 2) == 0
    }.collect {
        println(it)
    }
    
    
    // 오퍼레이트 해서 여러개를 쓸수도 있다. 
    (1..20).asFlow().filterNot {  // filter 와 차이 
        (it % 2) == 0
    }.map{
    	it * 3
    }.collect {
        println(it)
    }
    
}

 


transform 연산자

transform 연산자를 이용해 조금 더 유연하게 스트림을 변형할 수 있습니다.

 

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

suspend fun someCalc(i: Int): Int {
    delay(10L)
    return i * 2
}

fun main() = runBlocking<Unit> {
    (1..20).asFlow().transform {
        emit(it)
        emit(someCalc(it))
    }.collect {
        println(it)
    }
}

연산결과 
1
2
2
4
3
6
4
8
5
10 ...

take 연산자

take 연산자는 몇개의 수행 결과만 취합니다.

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

suspend fun someCalc(i: Int): Int {
    delay(10L)
    return i * 2
}

fun main() = runBlocking<Unit> {
    (1..20).asFlow().transform {
        emit(it)
        emit(someCalc(it))
    }.take(5)
    .collect {
        println(it)
    }
}

take (가져올 갯수)


takeWhile 연산자

takeWhile을 이용해 조건을 만족하는 동안만 값을 가져오게 할 수 있습니다.

 

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

suspend fun someCalc(i: Int): Int {
    delay(10L)
    return i * 2
}

fun main() = runBlocking<Unit> {
    (1..20).asFlow().transform {
        emit(it)
        emit(someCalc(it))
    }.takeWhile {
        it < 15
    }.collect {
        println(it)
    }
}

takeWhile {

    // 조건 

}

 


drop 연산자

drop 연산자는 처음 몇개의 결과를 버립니다. 

take가 takeWhile을 가지듯 dropWhile도 있습니다.

* dropWhile { // 조건 }  // 조건만큼 버린다. 

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

suspend fun someCalc(i: Int): Int {
    delay(10L)
    return i * 2
}

fun main() = runBlocking<Unit> {
    (1..20).asFlow().transform {
        emit(it)
        emit(someCalc(it))
    }.drop(5)
    .collect {
        println(it)
    }
    
    (1..20).asFlow().transform {
        emit(it)
        emit(someCalc(it))
    }.dropWhile{
    	it % 5 == 0 // 5의 배수는 버리겠다. 
    }
    .collect {
        println(it)
    }
    
    
    

    
}

 


reduce 연산자

collect, reduce, fold, toList, toSet과 같은 연산자는

플로우를 끝내는 함수라 종단 연산자(terminal operator)라고 합니다.

 

reduce는 흔히 map과 reduce로 함께 소개되는 함수형 언어의 오래된 메커니즘입니다.

첫번째 값을 결과에 넣은 후 각 값을 가져와 누진적으로 계산합니다.

 

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

suspend fun someCalc(i: Int): Int {
    delay(10L)
    return i * 2
}

fun main() = runBlocking<Unit> {
    val value = (1..10)
        .asFlow() // 1,2,3,4,5,6,7,8,9,10
        .reduce { a, b -> // (1,2) -> (3,3) -> (6,4) ...누진~
            a + b  // 3 -> 6 -> 10 ...  누진
        }
    println(value)
}

연산결과 
55

 


fold 연산자

fold 연산자는 reduce와 매우 유사합니다.

초기값이 있다는 차이만 있습니다.

 

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
​
suspend fun someCalc(i: Int): Int {
    delay(10L)
    return i * 2
}
​
fun main() = runBlocking<Unit> {
    val value = (1..10)
        .asFlow()
        .fold(10) { a, b ->  // (10, 1) -> (11 , 2) ...
            a + b // 11 -> 13 ...
        }
    println(value)
}
 
 

count 연산자

count의 연산자는 술어를 만족하는 자료의 갯수를 셉니다.

짝수의 갯수를 세어봅시다.

 

* filter는 술어를 만족하는 자료만 남기는데  count는 갯수만 센다. 

import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking<Unit> {
    val counter = (1..10)
        .asFlow()
        .count {
            (it % 2) == 0
        }
    println(counter)
}

 

종단 연산자 ( 특정 값, 컬렉션 등의 결과를 리턴한다. )  ex count -

중간 연산자 ( 아직 결과를 가져올수 없음 collect를 이용해서 결과를 가지고 와야 사용 할수 있다. )  ex filter 

728x90
반응형