Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin Sequences: Deep Dive

8b0334cfb942bef4267f86844fd941e5?s=47 Phil Shadlyn
November 16, 2020

Kotlin Sequences: Deep Dive

Android developers spend countless hours dealing with lists of data, and with the vast amount of collection operations available to us (think ‘map’, ‘filter’ or ‘sort’) it’s become easier than ever to manipulate that data into the format we want. But all that processing can come at a cost, as sometimes we sacrifice efficiency in the name of readable and concise code. It would be great if there was a way we could do both - be a good citizen when dealing with data, while also still using all the handy operations that we’ve grown to love...

Enter Kotlin Sequences! They offer a different take on iterating through data than a Collection, and in many cases allow you to work with your data more efficiently. Join us as we go through the ins and outs of Kotlin Sequences - what they are, when to use them, and what advantages they offer over traditional collections.

8b0334cfb942bef4267f86844fd941e5?s=128

Phil Shadlyn

November 16, 2020
Tweet

More Decks by Phil Shadlyn

Other Decks in Programming

Transcript

  1. Kotlin Sequences Deep Dive Phil Shadlyn | @physphil November 16,

    2020 #dcAmericas
  2. What is a Sequence?

  3. What are Kotlin Sequences? “A sequence is an iterable type

    that can be operated upon without creating unnecessary intermediate collections, by running all applicable operations on each element before moving onto the next.” https://typealias.com/guides/kotlin-sequences-illustrated-guide/
  4. Great... What does that mean?

  5. An Example • TV Show reference app • Display 10

    favourites and their rating • Consume API of 30,000 TV Shows
  6. data class NetworkTvShow( val id: String val title: String, val

    year: String?, val ratings: List<Int>?, val favourite: Boolean, val characters: List<Character>? ) data class TvShow( val title: String, val year: Int, val rating: Int, val favourite: Boolean ) Server model App model
  7. Order of operations: • Get list of shows from API

    • Filter by favourite • Convert network model to domain model • Take first 10 elements • Display in list
  8. val favouritesList = tvShowApi.getShowsList() .filter { it.favourite } .map {

    it.toTvShow() } .take(10) view.displayFavouriteList(favouritesList)
  9. val favouritesList = tvShowApi.getShowsList() .filter { it.favourite } .map {

    it.toTvShow() } .take(10) view.displayFavouriteList(favouritesList)
  10. val favouritesList = tvShowApi.getShowsList() .filter { it.favourite } .map {

    it.toTvShow() } .take(10) view.displayFavouriteList(favouritesList) New collection
  11. val favouritesList = tvShowApi.getShowsList() .filter { it.favourite } .map {

    it.toTvShow() } .take(10) view.displayFavouriteList(favouritesList) New collection
  12. val favouritesList = tvShowApi.getShowsList() .filter { it.favourite } .map {

    it.toTvShow() } .take(10) view.displayFavouriteList(favouritesList) New collection
  13. val favouritesList = tvShowApi.getShowsList() .filter { it.favourite } .map {

    it.toTvShow() } .take(10) view.displayFavouriteList(favouritesList)
  14. val favouritesList = tvShowApi.getShowsList() .filter { it.favourite } .map {

    it.toTvShow() } .take(10) 30,000 shows 31,941 operations 30,000 operations 1,931 operations 10 operations 3 new collections
  15. val favouritesList = tvShowApi.getShowsList() .asSequence() .filter { it.favourite } .map

    { it.toTvShow() } .take(10) .toList() 30,000 shows 39 operations 19 operations 10 operations 10 operations
  16. Whoa… what just happened?

  17. What are Kotlin Sequences? “A sequence is an iterable type

    that can be operated upon without creating unnecessary intermediate collections, by running all applicable operations on each element before moving onto the next.” https://typealias.com/guides/kotlin-sequences-illustrated-guide/
  18. The Wire Favourite Seinfeld Favourite Breaking Bad Game of Thrones

    Favourite Mad Men filter { it.favourite } The Wire Seinfeld Game of Thrones map { it.toTvShow() } The Wire Seinfeld Game of Thrones take(10) The Wire Seinfeld Game of Thrones … … … …
  19. Collection Processing • Operations executed eagerly • Operate on every

    element • Intermediate collections
  20. The Wire Favourite Seinfeld Favourite Breaking Bad Game of Thrones

    Favourite Mad Men filter { it.favourite } The Wire Seinfeld Game of Thrones map { it.toTvShow() } The Wire Seinfeld Game of Thrones take(10) The Wire Seinfeld Game of Thrones … …
  21. Sequence Processing • Operations executed lazily • One element at

    a time • Chain executed with terminal operator • No intermediate collections • Can short circuit
  22. Intermediate Operators • Return a Sequence • Build out operation

    chain • filter, map, take, etc...
  23. val favouritesList = tvShowApi.getShowsList() .asSequence() .filter { it.favourite } .map

    { it.toTvShow() } .take(10) .toList()
  24. Terminal Operators • Return a result • Trigger execution of

    operation chain • toList(), count(), maxOf(), etc...
  25. val favouritesList = tvShowApi.getShowsList() .asSequence() .filter { it.favourite } .map

    { it.toTvShow() } .take(10) .toList()
  26. Sequence Summary • Operations executed lazily • Execute chain on

    each item • Chain executed with terminal operator • No intermediate collections • Can short circuit
  27. How can I create a Sequence?

  28. Creating Sequences /** * Creates a [Sequence] instance that wraps

    the original * collection returning its elements when being iterated. */ public fun <T> Iterable<T>.asSequence(): Sequence<T> val showSequence = tvShowApi.getShowsList().asSequence()
  29. Creating Sequences /** * Creates a sequence that returns the

    specified values. */ public fun <T> sequenceOf(vararg elements: T): Sequence<T> val showSequence = sequenceOf(TheWire, Seinfeld, GameOfThrones)
  30. Creating Sequences /** * Returns a sequence defined by the

    starting value [seed] * and the function [nextFunction] */ public fun <T : Any> generateSequence( seed: T?, nextFunction: (T) -> T? ): Sequence<T> val incrementalSequence = generateSequence(1) { it + 1 }
  31. Should I use a Collection or Sequence?

  32. Use a Collection if: • Few items • Few operators

    • Stateful operations • Missing Sequence operators
  33. Use a Sequence if: • Many items • Many operations

    • Stateless operations • Short circuits
  34. Want to Learn More? • Kotlin Sequences docs https://kotlinlang.org/docs/reference/sequences.html •

    Kotlin Sequences: An Illustrated Guide https://typealias.com/guides/kotlin-sequences-illustrated-guide/ • Kotlin Sequence Tutorial https://winterbe.com/posts/2018/07/23/kotlin-sequence-tutorial/ • Kotlin Vocabulary: Collections and Sequences https://www.youtube.com/watch?v=77hfjIYwouw
  35. Thank You! Phil Shadlyn | @physphil November 16, 2020 #dcAmericas