Example var sum = 0.0 for (var i = 0; i <= prices.size; i++) { if (price[i] > 20) { sum += price[i] * 0.9 }} }} val prices = listOf(20, 12, 15, 21, 25, 28, 30)
Example val sum = prices .filter { price -> price > 20 } .map { price -> price * 0.9 } .sum() var sum = 0.0 for (price in prices) { if (price > 20) { sum += price * 0.9 }} }}
Example val sum = prices .filter { price -> price > 20 } .map { price -> price * 0.9 } .sum() Higher level, more readable & closer to the Business Intent
Example val sum = prices .filter { price -> price > 20 } .map { price -> price * 0.9 } .sum() var sum = 0.0 for (price in prices) { if (price > 20) { sum += price * 0.9 }} }}
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" }} val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" } .map { user -> user.posts }} val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" } .map { user -> user.posts } // Return type is: List<List<Post>> // But we need: List<Post> val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" } .map { user -> user.posts } val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" } .flatMap { user -> user.posts } val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" } .flatMap { user -> user.posts } // Returns a single list with all elements yielded from // [transform] invoked on on each element of original collection. fun <T, R> flatMap(transform: (T) -> Iterable<R>): List<R> val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" } .flatMap { user -> user.posts } // Returns a single list with all elements yielded from // [transform] invoked on on each element of original collection. fun <T, R> flatMap(transform: (T) -> Iterable<R>): List<R> val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" } .flatMap { user -> user.posts } // Returns a single list with all elements yielded from // [transform] invoked on on each element of original collection. fun <T, R> flatMap(transform: (T) -> Iterable<R>): List<R> val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" } .flatMap { user -> user.posts } val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .filter { user -> user.language == "PL" } .flatMap { user -> user.posts } .map { post -> post.body.length }} val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .take(100) .flatMap { user -> user.posts } .map { post -> post.body.length } .average() val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .take(100) .flatMap { user -> user.posts } .map { post -> post.body.length } .count() val users = db.getAllUsers()
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .take(100) .flatMap { user -> user.posts } .map { post -> post.body.length } .reduce { acc, length -> acc + length }} val users = db.getAllUsers() // Returns a single value computed by accumulating values // returned from applying [operation] to each element. fun <S, T:S> reduce(operation: (acc: S, T) -> S): S
User(val language: String, val posts: List<Post>) Example val avgPolishPostLength = users .take(100) .flatMap { user -> user.posts } .map { post -> post.body.length } .fold(0) { acc, _ -> acc + 1 }} val users = db.getAllUsers() // Accumulates value starting with [initial] and applying // [operation] to current accumulator value and each element. fun <T, R> fold(initial: R, operation: (acc: R, T) -> R): R
prone • Low-level details controlled by the library = may be optimized under the hood • More expressive, more readable • Easy to enhance & modify the logic • Closer to the business intent Benefits
filter(predicate: (T) -> Boolean): List<T> // Returns list containing elements transformed by [transform] fun <T, R> map(transform: (T) -> R): List<R> // Flattens nested lists into single list fun <T, R> flatMap(transform: (T) -> Iterable<R>): List<R> // Accumulates value by applying [operation] fun <S, T:S> reduce(operation: (acc: S, T) -> S): S // Accumulates value, starting with [initial] fun <T, R> fold(initial: R, operation: (acc: R, T) -> R): R Common Specialized Functions
(be declarative, avoid side-effects etc.) • RX is not an architecture. It's a Tool. So use it wisely • Subtask = flatMap • Remember that error = end of Stream
for creating, transforming & combining streams • Declarative threading • Cancellation of async tasks • Do not overuse for simple tasks Conclusions on RX