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

Use the Kotlin Stdlib, Luke (GDG DevFest Kaliningrad 2017)

Use the Kotlin Stdlib, Luke (GDG DevFest Kaliningrad 2017)

Kotlin is an amazing language to switch to. It has everything we missed in Java for all these years of stagnation. But while the language itself has a lot of powerful features, a lot less attention is devoted to its Standard library. A huge collection of tools and helpers for almost any case is made in the same pragmatic Kotlin fashion, being easy to use while built in a performant way.

In this talk I will cover which language features Standard library is based on, together with some implementation details, then review the most interesting parts of the library and introduce you to some useful, but rarely used pieces.

Join me to stop using Java habits and start writing your code the Kotlin-way!

Prior knowledge of Kotlin is not required. The talk will begin with a quick language crash course.

Sergey Ryabov

October 15, 2017
Tweet

More Decks by Sergey Ryabov

Other Decks in Programming

Transcript

  1. Kotlin Refresher val starWars = Movie("Star Wars") starWars = Movie("Star

    Trek") var epicMovie = Movie("2012") epicMovie = Movie("The Day After Tomorrow")
  2. Kotlin Refresher val starWars = Movie("Star Wars") starWars = Movie("Star

    Trek") // Only Star Wars can be Star Wars var epicMovie = Movie("2012") epicMovie = Movie("The Day After Tomorrow")
  3. Kotlin Refresher data class Movie(val title: String, var airYear: Int?

    = null) fun releaseMovie(movie: Movie) { movie.airYear = today() }
  4. Inline Functions fun nthFibonacciNumber(n: Int): Int { require (n >=

    0, "'n' must be non-negative, but was $n.") // ... } fun require(value: Boolean, message: String) { if (!value) throw IllegalArgumentException(message) }
  5. Inline Functions fun nthFibonacciNumber(n: Int): Int { require (n >=

    0) { "'n' must be non-negative, but was $n." } // ... } fun require(value: Boolean, lazyMessage: () -> String) { if (!value) throw IllegalArgumentException(lazyMessage()) }
  6. Inline Functions fun nthFibonacciNumber(n: Int): Int { require (n >=

    0) { "'n' must be non-negative, but was $n." } // ... } inline fun require(value: Boolean, lazyMessage: () -> String) { if (!value) throw IllegalArgumentException(lazyMessage()) }
  7. Inline Functions fun nthFibonacciNumber(n: Int): Int { if (!(n >=

    0)) throw IllegalArgumentException("'n' must be non-negative, but was $n.") // ... } inline fun require(value: Boolean, lazyMessage: () -> String) { if (!value) throw IllegalArgumentException(lazyMessage()) }
  8. Inline Functions. Preconditions // Throws AssertionError inline fun assert(value: Boolean)

    inline fun assert(value: Boolean, lazyMessage: () -> Any) // Throws IllegalArgumentException inline fun require(value: Boolean) inline fun require(value: Boolean, lazyMessage: () -> Any) inline fun requireNotNull(value: T?): T inline fun requireNotNull(value: T?, lazyMessage: () -> Any): T // Throws IllegalStateException inline fun check(value: Boolean) inline fun check(value: Boolean, lazyMessage: () -> Any) inline fun checkNotNull(value: T?): T inline fun checkNotNull(value: T?, lazyMessage: () -> Any): T // Throws IllegalStateException immediately inline fun error(message: Any)
  9. Extension Functions fun String.toInt(): Int = Integer.parseInt(this) public static final

    int toInt(@NotNull String $receiver) { return Integer.parseInt($receiver); }
  10. Extension Functions. Number Conversions inline fun String.toByte(radix: Int = 10):

    Byte inline fun String.toShort(radix: Int = 10): Short inline fun String.toInt(radix: Int = 10): Int inline fun String.toLong(radix: Int = 10): Long inline fun String.toFloat(): Float inline fun String.toDouble(): Double inline fun String.toBoolean(): Boolean inline fun Byte.toString(radix: Int): String inline fun Short.toString(radix: Int): String inline fun Int.toString(radix: Int): String inline fun Long.toString(radix: Int): String fun String.toByteOrNull(radix: Int = 10): Byte? fun String.toShortOrNull(radix: Int = 10): Short? fun String.toIntOrNull(radix: Int = 10): Int? fun String.toLongOrNull(radix: Int = 10): Long? fun String.toFloatOrNull(): Float? fun String.toDoubleOrNull(): Double?
  11. Operator Overloading operator fun plus(other: P): R // a +

    b, a += b operator fun minus(other: P): R // a - b, a -= b operator fun times(other: P): R // a * b, a *= b operator fun div(other: P): R // a / b, a /= b operator fun rem(other: P): R // a % b, a %= b operator fun plusAssign(other: P): Unit // a += b operator fun minusAssign(other: P): Unit // a -= b operator fun timesAssign(other: P): Unit // a *= b operator fun divAssign(other: P): Unit // a /= b operator fun remAssign(other: P): Unit // a %= b operator fun unaryPlus(): R // +a operator fun unaryMinus(): R // -a operator fun inc(): MyType // a++, ++a operator fun dec(): MyType // a--, --a operator fun not(): R // !a operator fun compareTo(other: P): Int // a >= b, a > b, a < b, a <= b operator fun equals(other: Any?): Boolean // a == b, a != b operator fun contains(other: P): Boolean // b in a, b !in a
  12. inline operator fun BigInteger.plus(other: BigInteger) : BigInteger inline operator fun

    BigInteger.minus(other: BigInteger) : BigInteger inline operator fun BigInteger.times(other: BigInteger) : BigInteger inline operator fun BigInteger.div(other: BigInteger) : BigInteger inline operator fun BigInteger.rem(other: BigInteger) : BigInteger inline operator fun BigInteger.unaryMinus() : BigInteger Operator Overloading. Big Numbers
  13. inline operator fun BigInteger.plus(other: BigInteger) : BigInteger inline operator fun

    BigInteger.minus(other: BigInteger) : BigInteger inline operator fun BigInteger.times(other: BigInteger) : BigInteger inline operator fun BigInteger.div(other: BigInteger) : BigInteger inline operator fun BigInteger.rem(other: BigInteger) : BigInteger inline operator fun BigInteger.unaryMinus() : BigInteger val enormousNumber = BigInteger("12345678909876543210") * BigInteger("42") Operator Overloading. Big Numbers
  14. inline operator fun BigInteger.plus(other: BigInteger) : BigInteger inline operator fun

    BigInteger.minus(other: BigInteger) : BigInteger inline operator fun BigInteger.times(other: BigInteger) : BigInteger inline operator fun BigInteger.div(other: BigInteger) : BigInteger inline operator fun BigInteger.rem(other: BigInteger) : BigInteger inline operator fun BigInteger.unaryMinus() : BigInteger val enormousNumber = BigInteger("12345678909876543210") * BigInteger("42") val enormousNumberV2 = -enormousNumber Operator Overloading. Big Numbers
  15. inline operator fun BigInteger.plus(other: BigInteger) : BigInteger inline operator fun

    BigInteger.minus(other: BigInteger) : BigInteger inline operator fun BigInteger.times(other: BigInteger) : BigInteger inline operator fun BigInteger.div(other: BigInteger) : BigInteger inline operator fun BigInteger.rem(other: BigInteger) : BigInteger inline operator fun BigInteger.unaryMinus() : BigInteger val enormousNumber = BigInteger("12345678909876543210") * BigInteger("42") val enormousNumberV2 = -enormousNumber if (BigInteger("42") > BigInteger.TEN) { println("Welcome, Captain Obvious!") } Operator Overloading. Big Numbers
  16. Operator Overloading operator fun invoke(p1: P1, ..., pN: PN): R

    // a(p1, ..., pN) operator fun get(p1: P1, ..., pN: PN): R // a[p1, ..., pN] operator fun set(p1: P1, ..., pN: PN, t: T): Unit // a[p1, ..., pN] = t operator fun rangeTo(other: P): R // a..b operator fun component1(): R // val myVal = MyType() operator fun componentN(): R // val (c1, ..., cN) = myVal operator fun iterator(): PseudoIterator // val myVal = MyType() // for (i in myVal) { class PseudoIterator { // ... operator fun next(): R // } operator fun hasNext(): Boolean }
  17. Operator Overloading operator fun invoke(p1: P1, ..., pN: PN): R

    // a(p1, ..., pN) operator fun get(p1: P1, ..., pN: PN): R // a[p1, ..., pN] operator fun set(p1: P1, ..., pN: PN, t: T): Unit // a[p1, ..., pN] = t operator fun rangeTo(other: P): R // a..b operator fun component1(): R // val myVal = MyType() operator fun componentN(): R // val (c1, ..., cN) = myVal operator fun iterator(): PseudoIterator // val myVal = MyType() // for (i in myVal) { class PseudoIterator { // ... operator fun next(): R // } operator fun hasNext(): Boolean }
  18. Operator Overloading. Iterators class MyType(private var value: Int) { private

    var divider: Int init { val pow10 = if (value == 0) 1 else Math.log10(value.toDouble()).toInt() divider = Math.pow(10.0, pow10.toDouble()).toInt() } operator fun next(): Int { val res = value / divider value %= divider divider /= 10 return res } operator fun hasNext() = divider > 0 }
  19. Function Literals with Receiver Map<String, String> headers = new ArrayMap<String,

    String>() {{ this.put("User-Agent", userAgent); if (userManager.isLoggedIn) { this.put("Authorization", userManager.accessToken); } }};
  20. Function Literals with Receiver inline fun <T> T.apply(block: T.() ->

    Unit): T { this.block(); return this } val headers = ArrayMap<String, String>().apply { this.put("User-Agent", userAgent) if (userManager.isLoggedIn) { this.put("Authorization", userManager.accessToken) } }
  21. Function Literals with Receiver inline fun <T> T.apply(block: T.() ->

    Unit): T { this.block(); return this } val headers = ArrayMap<String, String>().apply { put("User-Agent", userAgent) if (userManager.isLoggedIn) { put("Authorization", userManager.accessToken) } }
  22. var user: User? fun renderUser() { if (user != null)

    { nameView.text = user.name ageView.text = user.age } } Function Literals with Receiver
  23. var user: User? fun renderUser() { if (user != null)

    { nameView.text = user.name ageView.text = user.age } } Error! Smart cast to ‘User’ is impossible, because ‘user’ is a mutable property that could have been changed by this time. Function Literals with Receiver
  24. var user: User? fun renderUser() { val usr = user

    if (usr != null) { nameView.text = usr.name ageView.text = usr.age } } Function Literals with Receiver
  25. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? fun renderUser() { val usr = user if (usr != null) { nameView.text = usr.name ageView.text = usr.age } } Function Literals with Receiver
  26. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? fun renderUser() { user?.let { usr -> nameView.text = usr.name ageView.text = usr.age } } Function Literals with Receiver
  27. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? fun renderUser() { user?.let { nameView.text = it.name ageView.text = it.age } } Function Literals with Receiver
  28. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? fun renderUser() { user?.let { // ‘user’ is not null nameView.text = it.name ageView.text = it.age } } Function Literals with Receiver
  29. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? fun renderUser() { user?.let { // ‘user’ is not null and nameView.text = it.name ageView.text = it.age } } Function Literals with Receiver
  30. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? fun renderUser() { user?.let { // ‘user’ is not null and it was already read into local val nameView.text = it.name ageView.text = it.age } } Function Literals with Receiver
  31. Function Literals with Receiver inline fun <T, R> T.let(block: (T)

    -> R): R = block(this) fun fetchData() { getResponse()?.let { // result of ‘getResponse()’ was already read/delivered/calculated logResponse(it) saveData(parseData(it)) } }
  32. Function Literals with Receiver inline fun <T> T.apply(block: T.() ->

    Unit): T { block(); return this } inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this } inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block() inline fun <T, R> T.let(block: (T) -> R): R = block(this) inline fun <T, R> T.run(block: T.() -> R): R = block() inline fun <R> run(block: () -> R): R = block()
  33. Reified Type Parameters Map<Integer, String> int2Str = newMap(); <K,V> Map<K,

    V> newMap() { return new HashMap<K, V>(); } String[] strArr = newArray(42) <T> T[] newArray(int size) { return new T[size]; }
  34. Reified Type Parameters Map<Integer, String> int2Str = newMap(); <K,V> Map<K,

    V> newMap() { return new HashMap<K, V>(); } String[] strArr = newArray(42) <T> T[] newArray(int size) { return new T[size]; }
  35. Reified Type Parameters inline fun <reified T> arrayOfNulls(size: Int): Array<T?>

    = T[size] fun fill(dest: Array<String?>) { // ... } fill(arrayOfNulls(10))
  36. Reified Type Parameters. Arrays inline fun <reified T> arrayOfNulls(size: Int):

    Array<T?> // = T[size] inline fun <reified T> arrayOf(vararg elements: T): Array<T> // = T[] { elements } inline fun <reified T> emptyArray(): Array<T> // = T[0]
  37. Kotlin features Stdlib is based on • Inline Functions •

    Extension Functions • Operator Overloading • Function Literals with Receiver • Reified type parameters
  38. Collections fun <T> emptyList(): List<T> = EmptyList fun <T> listOf(element:

    T): List<T> = Collections.singletonList(element) fun <T> listOf([vararg elements: T]): List<T> fun <T> mutableListOf([vararg elements: T]): MutableList<T> // ArrayList fun <T> arrayListOf([vararg elements: T]): ArrayList<T> fun <T: Any> listOfNotNull(element: T?): List<T> fun <T: Any> listOfNotNull(vararg elements: T?): List<T> inline fun <T> List(size: Int, init: (index: Int) -> T): List<T> inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableList<T>
  39. fun <T> emptySet(): Set<T> = EmptySet fun <T> setOf(element: T):

    Set<T> = Collections.singleton(element) fun <T> setOf([vararg elements: T]): Set<T> fun <T> mutableSetOf([vararg elements: T]): MutableSet<T> // LinkedHashSet fun <T> hashSetOf([vararg elements: T]): HashSet<T> fun <T> linkedSetOf([vararg elements: T]): LinkedHashSet<T> fun <T> sortedSetOf([comparator: Comparator<in T>,] vararg elements: T): TreeSet<T> Collections
  40. Collections val <T> List<T>.lastIndex: Int get() = this.size - 1

    inline fun <T> Collection<T>?.orEmpty(): Collection<T> inline fun <T> List<T>?.orEmpty(): List<T>
  41. Collections inline operator fun <T> List<T>.component1(): T inline operator fun

    <T> List<T>.component5(): T operator fun <T> Iterable<T>.contains(element: T): Boolean operator fun <T> Collection<T>.plus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> operator fun <T> Iterable<T>.plus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> operator fun <T> Iterable<T>.minus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T>
  42. Collections inline operator fun <T> List<T>.component1(): T inline operator fun

    <T> List<T>.component5(): T operator fun <T> Iterable<T>.contains(element: T): Boolean operator fun <T> Collection<T>.plus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> operator fun <T> Iterable<T>.plus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> operator fun <T> Iterable<T>.minus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> val (s1, s2, s3, s4, s5) = listOf<String>(...)
  43. Collections inline operator fun <T> List<T>.component1(): T inline operator fun

    <T> List<T>.component5(): T operator fun <T> Iterable<T>.contains(element: T): Boolean operator fun <T> Collection<T>.plus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> operator fun <T> Iterable<T>.plus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> operator fun <T> Iterable<T>.minus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> if ("Jan" in months) { // ... }
  44. Collections inline operator fun <T> List<T>.component1(): T inline operator fun

    <T> List<T>.component5(): T operator fun <T> Iterable<T>.contains(element: T): Boolean operator fun <T> Collection<T>.plus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> operator fun <T> Iterable<T>.plus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> operator fun <T> Iterable<T>.minus(T|Array<out T>|Iterable<T>|Sequence<T>): List<T> androidLanguagesList += "Kotlin"
  45. Collections. Search inline fun <T> Iterable<T>.first([predicate: (T) -> Boolean]): T

    inline fun <T> Iterable<T>.last([predicate: (T) -> Boolean]): T inline fun <T> Iterable<T>.firstOrNull([predicate: (T) -> Boolean]): T? inline fun <T> Iterable<T>.lastOrNull([predicate: (T) -> Boolean]): T? inline fun <T> Iterable<T>.find(predicate: (T) -> Boolean): T? // = firstOrNull() inline fun <T> Iterable<T>.findLast(predicate: (T) -> Boolean): T? // = lastOrNull() inline fun <T> Iterable<T>.single([predicate: (T) -> Boolean]): T inline fun <T> Iterable<T>.singleOrNull([predicate: (T) -> Boolean]): T
  46. Collections. Search fun <T> Iterable<T>.indexOf(element: T): Int fun <T> Iterable<T>.lastIndexOf(element:

    T): Int inline fun <T> Iterable<T>.indexOfFirst(predicate: (T) -> Boolean): Int inline fun <T> Iterable<T>.indexOfLast(predicate: (T) -> Boolean): Int fun <T> List<T>.binarySearch([from: Int, to: Int,] comparison: (T) -> Int): Int fun <T: Comparable<T>> List<T?>.binarySearch(elem: T?, [from: Int, to: Int]): Int fun <T> List<T>. binarySearch(elem: T, comparator: Comparator<in T>, [from: Int, to: Int]): Int inline fun <T, K: Comparable<K>> List<T>. binarySearchBy(key: K?, [from: Int, to: Int,] selector: (T) -> K?): Int
  47. Collections. Filtering inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T>

    inline fun <T> Iterable<T>.filterIndexed(predicate: (index: Int, T) -> Boolean): List<T> inline fun <T> Iterable<T>.filterNot(predicate: (T) -> Boolean): List<T> fun <T: Any> Iterable<T?>.filterNotNull(): List<T> inline fun <T, C: MutableCollection<in T>> Iterable<T>. filterTo(dest: C, predicate: (T) -> Boolean): C filterIndexedTo(dest: C, predicate: (index: Int, T) -> Boolean): C filterNotTo(dest: C, predicate: (T) -> Boolean): C fun <C: MutableCollection<in T>, T : Any> Iterable<T?>.filterNotNullTo(dest: C): C fun <R> Iterable<*>.filterIsInstance(klass: Class<R>): List<R> inline fun <reified R> Iterable<*>.filterIsInstance(): List<R> fun <C: MutableCollection<in R>, R> Iterable<*>. filterIsInstanceTo(dest: C, klass: Class<R>): C inline fun <reified R, C: MutableCollection<in R>> Iterable<*>. filterIsInstanceTo(dest: C): C
  48. Collections. Filtering fun <T> MutableIterable<T>.removeAll(cond: (T) -> Boolean): Boolean //

    filterNotInPlace() fun <T> MutableIterable<T>.retainAll(cond: (T) -> Boolean): Boolean // filterInPlace() fun <T> MutableCollection<in T>.removeAll(Array<out T>|Iterable<T>|Sequence<T>): Boolean fun <T> MutableCollection<in T>.retainAll(Array<out T>|Iterable<T>|Sequence<T>): Boolean
  49. Collections. Filtering fun <T> Iterable<T>.take(n: Int): List<T> fun <T> List<T>.takeLast(n:

    Int): List<T> inline fun <T> Iterable<T>.takeWhile(predicate: (T) -> Boolean): List<T> inline fun <T> List<T>.takeLastWhile(predicate: (T) -> Boolean): List<T> fun <T> Iterable<T>.drop(n: Int): List<T> fun <T> List<T>.dropLast(n: Int): List<T> inline fun <T> Iterable<T>.dropWhile(predicate: (T) -> Boolean): List<T> inline fun <T> List<T>.dropLastWhile(predicate: (T) -> Boolean): List<T>
  50. Collections. Sorting fun <T: Comparable<T>> Iterable<T>.sorted(): List<T> fun <T: Comparable<T>>

    Iterable<T>.sortedDescending(): List<T> fun <T: Comparable<T>> MutableList<T>.sort(): Unit fun <T: Comparable<T>> MutableList<T>.sortDescending(): Unit inline fun <T, R: Comparable<R>> Iterable<T>.sortedBy(selector: (T) -> R?): List<T> inline fun <T, R: Comparable<R>> Iterable<T>.sortedByDescending(selector: (T) -> R?): List<T> inline fun <T, R: Comparable<R>> MutableList<T>.sortBy(selector: (T) -> R?): Unit inline fun <T, R: Comparable<R>> MutableList<T>.sortByDescending(selector: (T) -> R?): Unit fun <T> Iterable<T>.sortedWith(comparator: Comparator<in T>): List<T> fun <T> MutableList<T>.sortWith(comparator: Comparator<in T>): Unit
  51. Collections. Reversing & Slicing fun <T> Iterable<T>.reversed(): List<T> fun <T>

    MutableList<T>.reverse(): Unit fun <T> List<T>.asReversed(): List<T> fun <T> MutableList<T>.asReversed(): MutableList<T> fun <T> List<T>.slice(indices: IntRange): List<T> fun <T> List<T>.slice(indices: Iterable<Int>): List<T>
  52. Collections. Mapping inline fun <T, K, V> Iterable<T>. associate(transform: (T)

    -> Pair<K, V>): Map<K, V> associateBy(keySelector: (T) -> K, [valueTransform: (T) -> V]): Map<K, V> inline fun <T, K, V, M: MutableMap<in K, in V>> Iterable<T>. associateTo(dest: M, transform: (T) -> Pair<K, V>): M associateByTo(dest: M, keySelector: (T) -> K, [valueTransform: (T) -> V]): M
  53. Collections. Mapping inline fun <T, R> Iterable<T>. map(transform: (T) ->

    R): List<R> mapIndexed(transform: (index: Int, T) -> R): List<R> inline fun <T, R: Any> Iterable<T>. mapNotNull(transform: (T) -> R?): List<R> mapIndexedNotNull(transform: (index: Int, T) -> R?): List<R> inline fun <T, R, C: MutableCollection<in R>> Iterable<T>. mapTo(dest: C, transform: (T) -> R): C mapIndexedTo(dest: C, transform: (index: Int, T) -> R): C inline fun <T, R: Any, C: MutableCollection<in R>> Iterable<T>. mapNotNullTo(dest: C, transform: (T) -> R?): C mapIndexedNotNullTo(dest: C, transform: (index: Int, T) -> R?): C
  54. Collections. Mapping & Grouping inline fun <T> Iterable<T>.forEach(action: (T) ->

    Unit): Unit inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit inline fun <T, C: Iterable<T>> C.onEach(action: (T) -> Unit): C inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R> inline fun <T, R, C: MutableCollection<in R>> Iterable<T>. flatMapTo(dest: C, transform: (T) -> Iterable<R>): C inline fun <T, K, V> Iterable<T>. groupBy(keySelector: (T) -> K, [valueTransform: (T) -> V]): Map<K, List<V>> inline fun <T, K, V, M: MutableMap<in K, MutableList<V>>> Iterable<T>. groupByTo(dest: M, keySelector: (T) -> K, [valueTransform: (T) -> V]): M inline fun <T, K> Iterable<T>.groupingBy(keySelector: (T) -> K): Grouping<T, K>
  55. Collections. Misc fun <T> Iterable<T>.distinct(): List<T> inline fun <T, K>

    Iterable<T>.distinctBy(selector: (T) -> K): List<T> fun <T> Iterable<Iterable<T>>.flatten(): List<T> infix fun <T, R> Iterable<T>.zip(Array<out R>|Iterable<R>): List<Pair<T, R>> inline fun <T, R, V> Iterable<T>. zip(Array<out R>|Iterable<R>, transform: (a: T, b: R) -> V): List<V> fun <T, R> Iterable<Pair<T, R>>.unzip(): Pair<List<T>, List<R>> inline fun <T> Iterable<T>.partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>> infix fun <T> Iterable<T>.intersect(other: Iterable<T>): Set<T> infix fun <T> Iterable<T>.subtract(other: Iterable<T>): Set<T> infix fun <T> Iterable<T>.union(other: Iterable<T>): Set<T>
  56. Collections. Aggregation fun Iterable<Int>.average(): Double fun Iterable<Int>.sum(): Int inline fun

    <T> Iterable<T>.sumBy(selector: (T) -> Int): Int inline fun <T> Iterable<T>.sumByDouble(selector: (T) -> Double): Double inline fun <T> Iterable<T>.count([predicate: (T) -> Boolean]): Int fun <T: Comparable<T>> Iterable<T>.max(): T? fun <T: Comparable<T>> Iterable<T>.min(): T? inline fun <T, R: Comparable<R>> Iterable<T>.maxBy(selector: (T) -> R): T? inline fun <T, R: Comparable<R>> Iterable<T>.minBy(selector: (T) -> R): T? fun <T> Iterable<T>.maxWith(comparator: Comparator<in T>): T? fun <T> Iterable<T>.minWith(comparator: Comparator<in T>): T? inline fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean inline fun <T> Iterable<T>.any([predicate: (T) -> Boolean]): Boolean inline fun <T> Iterable<T>.none([predicate: (T) -> Boolean]): Boolean
  57. Collections. Folding & Reducing inline fun <T, R> Iterable<T>. fold(initial:

    R, operation: (acc: R, T) -> R): R foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R inline fun <T, R> List<T>. foldRight(initial: R, operation: (T, acc: R) -> R): R foldRightIndexed(initial: R, operation: (index: Int, T, acc: R) -> R): R inline fun <S, T: S> Iterable<T>. reduce(operation: (acc: S, T) -> S): S reduceIndexed(operation: (index: Int, acc: S, T) -> S): S inline fun <S, T: S> List<T>. reduceRight(operation: (T, acc: S) -> S): S reduceRightIndexed(operation: (index: Int, T, acc: S) -> S): S
  58. Collections. ToString fun <T> Iterable<T>.joinToString( separator: CharSequence = ", ",

    prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String fun <T, A : Appendable> Iterable<T>.joinTo( buffer: A, sep: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A
  59. Here goes all the same stuff for Arrays, Sequences and

    CharSequences... ...if applicable
  60. Collections. Conversion fun <T, C: MutableCollection<in T>> Iterable<T>.toCollection(dest: C): C

    fun <T> Iterable<T>.toList(): List<T> fun <T> Iterable<T>.toMutableList(): MutableList<T> fun <T> Iterable<T>.toSet(): Set<T> fun <T> Iterable<T>.toMutableSet(): MutableSet<T> fun <T> Iterable<T>.toHashSet(): HashSet<T> fun <T: Comparable<T>> Iterable<T>.toSortedSet([comparator: Comparator<in T>]): SortedSet<T> inline fun <reified T> Collection<T>.toTypedArray(): Array<T> inline fun <T> Iterable<T>.asIterable(): Iterable<T> fun <T> Iterable<T>.asSequence(): Sequence<T>
  61. Collections. Conversion fun <T, C: MutableCollection<in T>> Iterable<T>.toCollection(dest: C): C

    fun <T> Iterable<T>.toList(): List<T> fun <T> Iterable<T>.toMutableList(): MutableList<T> fun <T> Iterable<T>.toSet(): Set<T> fun <T> Iterable<T>.toMutableSet(): MutableSet<T> fun <T> Iterable<T>.toHashSet(): HashSet<T> fun <T: Comparable<T>> Iterable<T>.toSortedSet([comparator: Comparator<in T>]): SortedSet<T> inline fun <reified T> Collection<T>.toTypedArray(): Array<T> inline fun <T> Iterable<T>.asIterable(): Iterable<T> fun <T> Iterable<T>.asSequence(): Sequence<T>
  62. Collections. Conversion fun <T, C: MutableCollection<in T>> Iterable<T>.toCollection(dest: C): C

    fun <T> Iterable<T>.toList(): List<T> fun <T> Iterable<T>.toMutableList(): MutableList<T> fun <T> Iterable<T>.toSet(): Set<T> fun <T> Iterable<T>.toMutableSet(): MutableSet<T> fun <T> Iterable<T>.toHashSet(): HashSet<T> fun <T: Comparable<T>> Iterable<T>.toSortedSet([comparator: Comparator<in T>]): SortedSet<T> inline fun <reified T> Collection<T>.toTypedArray(): Array<T> inline fun <T> Iterable<T>.asIterable(): Iterable<T> fun <T> Iterable<T>.asSequence(): Sequence<T>
  63. data class User(val birthday: Date, val movies: List<String>) data class

    Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) Collections
  64. data class User(val birthday: Date, val movies: List<String>) data class

    Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() Collections
  65. data class User(val birthday: Date, val movies: List<String>) data class

    Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } Collections
  66. data class User(val birthday: Date, val movies: List<String>) data class

    Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } Collections
  67. data class User(val birthday: Date, val movies: List<String>) data class

    Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } Collections
  68. data class User(val birthday: Date, val movies: List<String>) data class

    Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } Collections
  69. data class User(val birthday: Date, val movies: List<String>) data class

    Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } Collections
  70. data class User(val birthday: Date, val movies: List<String>) data class

    Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Collections
  71. repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title

    in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Collections
  72. repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title

    in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .joinToString(separator = "\n", prefix = "My movie preferences by genre:\n") { (genre, count, _) -> "$genre movies watched: $count" } Collections
  73. fun <T> emptySequence(): Sequence<T> = EmptySequence fun <T> sequenceOf(vararg elements:

    T): Sequence<T> fun <T: Any> generateSequence(nextFunction: () -> T?): Sequence<T> generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence<T> generateSequence(seedFunction: () -> T?, nextFunction: (T) -> T?): Sequence<T> inline fun <T> Sequence(iterator: () -> Iterator<T>): Sequence<T> fun <T> Sequence<T>.constrainOnce(): Sequence<T> Sequences
  74. fun genFibonacciSequence(): Sequence<Int> = generateSequence(0 to 1) { (prev, next)

    -> next to (prev + next) }.map { (next, _) -> next } Sequences
  75. fun genFibonacciSequence(): Sequence<Int> = generateSequence(0 to 1) { (prev, next)

    -> next to (prev + next) }.map { (next, _) -> next } genFibonacciSequence() .takeWhile { it < 100 } .forEach(::println) Sequences
  76. fun genFibonacciSequence(): Sequence<Int> = generateSequence(0 to 1) { (prev, next)

    -> next to (prev + next) }.map { (next, _) -> next } genFibonacciSequence() .takeWhile { it < 100 } .forEach(::println) // 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 Sequences
  77. repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title

    in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Sequences
  78. repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title

    in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Sequences
  79. repo.getMovies() .asSequence() .filter { it.airDate > user.birthday } .filter {

    it.title in user.movies } .groupBy { it.genre } .asSequence() .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Sequences
  80. repo.getMovies() .asSequence() .filter { it.airDate > user.birthday } .filter {

    it.title in user.movies } .groupBy { it.genre } .asSequence() .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Sequences
  81. fun <K, V> emptyMap(): Map<K, V> = EmptyMap fun <K,

    V> mapOf(p: Pair<K, V>): Map<K, V> = Collections.singletonMap(p.first, p.second) fun <K, V> mapOf([vararg pairs: Pair<K, V>]): Map<K, V> fun <K, V> mutableMapOf([vararg pairs: Pair<K, V>]): MutableMap<K, V> // LinkedHashMap fun <K, V> hashMapOf([vararg pairs: Pair<K, V>]): HashMap<K, V> fun <K, V> linkedMapOf([vararg pairs: Pair<K, V>]): LinkedHashMap<K, V> fun <K: Comparable<K>, V> sortedMapOf(vararg pairs: Pair<K, V>): SortedMap<K, V> inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V inline fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V Maps
  82. fun <K, V> emptyMap(): Map<K, V> = EmptyMap fun <K,

    V> mapOf(p: Pair<K, V>): Map<K, V> = Collections.singletonMap(p.first, p.second) fun <K, V> mapOf([vararg pairs: Pair<K, V>]): Map<K, V> fun <K, V> mutableMapOf([vararg pairs: Pair<K, V>]): MutableMap<K, V> // LinkedHashMap fun <K, V> hashMapOf([vararg pairs: Pair<K, V>]): HashMap<K, V> fun <K, V> linkedMapOf([vararg pairs: Pair<K, V>]): LinkedHashMap<K, V> fun <K: Comparable<K>, V> sortedMapOf(vararg pairs: Pair<K, V>): SortedMap<K, V> inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V inline fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V Maps
  83. inline fun <K, V> Map<out K, V>. filterKeys(predicate: (K) ->

    Boolean): Map<K, V> filterValues(predicate: (V) -> Boolean): Map<K, V> inline fun <K, V, R> Map<out K, V>. mapKeys(transform: (Map.Entry<K, V>) -> R): Map<R, V> mapValues(transform: (Map.Entry<K, V>) -> R): Map<K, R> Maps. Extra
  84. Maps fun wordCount(list: List<String>): Map<String, Int> { val map =

    mutableMapOf<String, Int>() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item] + 1 } return map }
  85. Maps fun wordCount(list: List<String>): Map<String, Int> { val map =

    mutableMapOf<String, Int>() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item] + 1 } return map } Error! Operator plus is not allowed on a nullable receiver.
  86. Maps fun wordCount(list: List<String>): Map<String, Int> { val map =

    mutableMapOf<String, Int>() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item]!! + 1 } return map }
  87. Maps fun wordCount(list: List<String>): Map<String, Int> { val map =

    mutableMapOf<String, Int>() for (item in list) { map[item] = (map[item] ?: 0) + 1 } return map }
  88. Maps fun wordCount(list: List<String>): Map<String, Int> { val map =

    mutableMapOf<String, Int>() for (item in list) { map[item] = map.getOrElse(item) { 0 } + 1 } return map }
  89. Maps with Default fun <K, V> Map<K, V>.withDefault(defaultValue: (key: K)

    -> V): Map<K, V> Warning! Does not change Map.get() semantics! Use Map.getValue() fun <K, V> Map<K, V>.getValue(key: K): V
  90. Maps with Default fun wordCount(list: List<String>): Map<String, Int> { val

    map = mutableMapOf<String, Int>().withDefault { 0 } for (item in list) { map[item] = map.getValue(item) + 1 } return map }
  91. inline fun <T, K> Iterable<T>.groupingBy(keySelector: (T) -> K): Grouping<T, K>

    interface Grouping<T, out K> { fun sourceIterator(): Iterator<T> fun keyOf(element: T): K } Grouping
  92. Grouping inline fun <T, K> Iterable<T>.groupingBy(keySelector: (T) -> K): Grouping<T,

    K> interface Grouping<T, out K> { fun sourceIterator(): Iterator<T> fun keyOf(element: T): K } inline fun <T, K, R> Grouping<T, K>. aggregate(op: (key: K, accumulator: R?, elem: T, first: Boolean) -> R): Map<K, R>
  93. Grouping fun wordCount(list: List<String>): Map<String, Int> { return list .groupingBy

    { word -> word } .aggregate { key, acc, elem, first -> (acc ?: 0) + 1 } }
  94. Grouping fun wordCount(list: List<String>): Map<String, Int> = list.groupingBy { it

    } .aggregate { _, acc, _, _ -> (acc ?: 0) + 1 } fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int>
  95. Grouping fun wordCount(list: List<String>): Map<String, Int> = list.groupingBy { it

    }.eachCount() fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int>
  96. Grouping fun wordCount(list: List<String>): Map<String, Int> = list.groupingBy { it

    }.eachCount() fun wordCount(list: List<String>): Map<String, Int> { val map = mutableMapOf<String, Int>() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item]!! + 1 } return map }
  97. Grouping inline fun <T, K, R> Grouping<T, K>. fold(initialValue: R,

    operation: (accumulator: R, element: T) -> R): Map<K, R> fold(initialValueSelector: (key: K, element: T) -> R, operation: (key: K, accumulator: R, element: T) -> R): Map<K, R> inline fun <S, T: S, K> Grouping<T, K>. reduce(operation: (key: K, accumulator: S, element: T) -> S): Map<K, S>
  98. Comparisons fun <T: Comparable<T>> maxOf(a: T, b: T, [c: T]):

    T fun <T: Comparable<T>> minOf(a: T, b: T, [c: T]): T // + variants for primitive numbers inline fun <T: Comparable<T>> nullsFirst(): Comparator<T?> inline fun <T: Comparable<T>> nullsLast(): Comparator<T?> fun <T: Any> nullsFirst(comparator: Comparator<in T>): Comparator<T?> fun <T: Any> nullsLast(comparator: Comparator<in T>): Comparator<T?> fun <T: Comparable<T>> naturalOrder(): Comparator<T> fun <T: Comparable<T>> reverseOrder(): Comparator<T> fun <T> Comparator<T>.reversed(): Comparator<T>
  99. Comparisons fun <T> compareBy(vararg selectors: (T) -> Comparable<*>?): Comparator<T> inline

    fun <T> compareBy(selector: (T) -> Comparable<*>?): Comparator<T> inline fun <T, K> compareBy(Comparator<in K>, selector: (T) -> K): Comparator<T>
  100. Comparisons inline fun <T> Comparator<T>. thenComparator(comparison: (a: T, b: T)

    -> Int): Comparator<T> thenBy(selector: (T) -> Comparable<*>?): Comparator<T> thenByDescending(selector: (T) -> Comparable<*>?): Comparator<T> inline fun <T, K> Comparator<T>. thenBy(Comparator<in K>, selector: (T) -> K): Comparator<T> thenByDescending(Comparator<in K>, selector: (T) -> K): Comparator<T> infix fun <T> Comparator<T>. then(comparator: Comparator<in T>): Comparator<T> thenDescending(comparator: Comparator<in T>): Comparator<T>
  101. Comparisons data class Movie(val title: String, val airYear: Int, val

    posterUrl: String, val likesCount: Int, val genre: Genre, val actors: List<Actor>) enum class Genre { COMEDY, ACTION, DRAMA, DOCUMENTARY } getMovies() .sortedWith(movieComparator) .filterNot { it.title in user.movies } .take(100)
  102. Comparisons val movieComparator = compareBy<Movie>(Movie::airYear) .thenBy(Movie::likesCount) .thenByDescending { it.actors.size }

    val genreComparator = compareBy<Genre> { when (it) { Genre.ACTION -> 40 Genre.DOCUMENTARY -> 30 Genre.COMEDY -> 20 Genre.DRAMA -> 10 } }
  103. Comparisons val movieComparator = compareBy<Movie>(Movie::airYear) .thenBy(genreComparator) { it.genre } .thenBy(Movie::likesCount)

    .thenByDescending { it.actors.size } val genreComparator = compareBy<Genre> { when (it) { Genre.ACTION -> 40 Genre.DOCUMENTARY -> 30 Genre.COMEDY -> 20 Genre.DRAMA -> 10 } }
  104. Comparisons val movieComparator = compareBy<Movie>(Movie::airYear) .thenBy(genreComparator) { it.genre } .thenBy(Movie::likesCount)

    .thenByDescending { it.actors.size } .reversed() val genreComparator = compareBy<Genre> { when (it) { Genre.ACTION -> 40 Genre.DOCUMENTARY -> 30 Genre.COMEDY -> 20 Genre.DRAMA -> 10 } }
  105. Text fun String.capitalize(): String fun String.decapitalize(): String fun CharSequence.isBlank(): Boolean

    inline fun CharSequence?.isNullOrBlank(): Boolean inline fun CharSequence?.isNullOrEmpty(): Boolean // Farewell TextUtils.isEmpty() fun CharSequence. commonPrefixWith(other: CharSequence, [ignoreCase: Boolean]): String commonSuffixWith(other: CharSequence, [ignoreCase: Boolean]): String splitToSequence(vararg delimiters: String, [ignoreCase: Boolean, limit: Int]): Sequence<String> fun CharSequence.lineSequence(): Sequence<String>
  106. IO. Closeable inline fun <T : Closeable?, R> T.use(block: (T)

    -> R): R inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R
  107. IO. Closeable inline fun <T : Closeable?, R> T.use(block: (T)

    -> R): R inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R fun InputStream.readLines(): List<String> = BufferedReader(InputStreamReader(this)).use { val lines = arrayListOf<String>() var line = it.readLine() while (line != null) { lines += line line = it.readLine() } lines }
  108. IO. Byte Streams inline fun InputStream. buffered([bufferSize: Int]): BufferedInputStream reader([charset:

    Charset]): InputStreamReader bufferedReader([charset: Charset]): BufferedReader inline fun OutputStream. buffered([bufferSize: Int]): BufferedOutputStream writer([charset: Charset]): OutputStreamWriter bufferedWriter([charset: Charset]): BufferedWriter fun InputStream.copyTo(out: OutputStream, [bufferSize: Int]): Long
  109. inline fun Reader.buffered([bufferSize: Int]): BufferedReader inline fun Writer.buffered([bufferSize: Int]): BufferedWriter

    fun Reader.readText(): String fun Reader.readLines(): List<String> fun BufferedReader.lineSequence(): Sequence<String> inline fun <T> Reader.useLines(block: (Sequence<String>) -> T): T fun Reader.forEachLine(action: (String) -> Unit): Unit fun Reader.copyTo(out: Writer, [bufferSize: Int]): Long IO. Text Streams
  110. IO. Files inline fun File.inputStream(): FileInputStream inline fun File.outputStream(): FileOutputStream

    inline fun File.reader([charset: Charset]): InputStreamReader inline fun File.writer([charset: Charset]): OutputStreamWriter inline fun File.bufferedReader([charset: Charset, bufferSize: Int]): BufferedReader inline fun File.bufferedWriter([charset: Charset, bufferSize: Int]): BufferedWriter inline fun File.printWriter([charset: Charset]): PrintWriter
  111. IO. Files fun File.readBytes(): ByteArray fun File.writeBytes(array: ByteArray): Unit fun

    File.appendBytes(array: ByteArray): Unit fun File.readText([charset: Charset]): String fun File.writeText(text: String, [charset: Charset]): Unit fun File.appendText(text: String, [charset: Charset]): Unit fun File.readLines([charset: Charset]): List<String> inline fun <T> File.useLines([charset: Charset], block: (Sequence<String>) -> T): T fun File.forEachLine([charset: Charset], action: (String) -> Unit): Unit fun File.forEachBlock([blockSize: Int,] action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit
  112. IO. Files val wordCount = File("shakespeare.txt").useLines { it.flatMap { it.splitToSequence('

    ', ',', '.', '!', '?') } .map { it.toLowerCase() } .groupingBy { it } .eachCount() }
  113. IO. Files val wordCount = File("shakespeare.txt").useLines { it.flatMap { it.splitToSequence('

    ', ',', '.', '!', '?') } .map { it.toLowerCase() } .groupingBy { it } .eachCount() }
  114. IO. Files val wordCount = File("shakespeare.txt").bufferedReader().use { it.lineSequence().flatMap { it.splitToSequence('

    ', ',', '.', '!', '?') } .map { it.toLowerCase() } .groupingBy { it } .eachCount() }
  115. IO. Files val File.extension: String val File.invariantSeparatorsPath: String val File.nameWithoutExtension:

    String fun File.toRelativeString(base: File): String fun File.relativeTo(base: File): File fun File.relativeToOrSelf(base: File): File fun File.relativeToOrNull(base: File): File? fun File.resolve(relative: String|File): File fun File.resolveSibling(relative: String|File): File fun File.startsWith(other: String|File): Boolean fun File.endsWith(other: String|File): Boolean
  116. IO. Files fun createTempDir(prefix: String = "tmp", [suffix: String?, directory:

    File?]): File fun createTempFile(prefix: String = "tmp", [suffix: String?, directory: File?]): File fun File.copyTo(target: File, overwrite: Boolean = false, [bufferSize: Int]): File fun File.copyRecursively(target: File, overwrite: Boolean = false, [onError: (File, IOException) -> OnErrorAction]): Boolean fun File.deleteRecursively(): Boolean
  117. Goodies. Ranges fun processResponse(response: Response) = when (response.code) { in

    200..299 -> ok(response) in 400..499 -> clientError(response) in 500..599 -> serverError(response) else -> throw IllegalStateException("Bummer")
  118. Goodies. Ranges fun processResponse(response: Response) = when (response.code) { in

    200..299 -> ok(response) in 400..499 -> clientError(response) in 500..599 -> serverError(response) else -> throw IllegalStateException("Bummer") public static final int processResponse(@NotNull Response response) { int code = response.code(); int result; if (200 <= code && code <= 299) { result = ok(response); } else if (400 <= code && code <= 499) { result = clientError(response); } else if (500 <= code && code <= 599) { result = serverError(response); } else { throw new IllegalStateException("Bummer"); } }
  119. Goodies. Locks inline fun <T> Lock.withLock(action: () -> T): T

    inline fun <T> ReentrantReadWriteLock.read(action: () -> T): T inline fun <T> ReentrantReadWriteLock.write(action: () -> T): T
  120. Goodies. Locks inline fun <T> Lock.withLock(action: () -> T): T

    inline fun <T> ReentrantReadWriteLock.read(action: () -> T): T inline fun <T> ReentrantReadWriteLock.write(action: () -> T): T val dbLock = ReentrantReadWriteLock() dbLock.write { writeToDb(entity) }
  121. inline fun measureNanoTime(block: () -> Unit) : Long inline fun

    measureTimeMillis(block: () -> Unit) : Long Goodies. System
  122. inline fun measureNanoTime(block: () -> Unit) : Long inline fun

    measureTimeMillis(block: () -> Unit) : Long val saveTime = measureNanoTime { writeToDb(entity) } println("Saving is soo sloow ${saveTime}ns") Goodies. System
  123. Goodies. Targeting Java 8 fun <T> Stream<T>.toList(): List<T> fun <T>

    Stream<T>.asSequence(): Sequence<T> fun <T> Sequence<T>.asStream(): Stream<T>
  124. Takeaways • No big inline method bodies • Public API

    in public inline functions • Reified functions are not present in bytecode • Eager collection processing functions • Use Sequence • “as”/”to” prefix convention • Ranges optimisations
  125. What was left behind • Hidden costs of language constructs

    ◦ Exploring Kotlin’s hidden costs  series, https://goo.gl/Gh4uxK • @Jvm* annotations - Kotlin->Java interop ◦ Writing Java-friendly Kotlin code, Mobius https://goo.gl/mXedcb • @DslMarker ◦ Fantastic DSLs and Where to Find Them, https://goo.gl/vcGmmG • Different Annotation targets • Reflection • Coroutines ◦ Корутины в Kotlin - Роман Елизаров, https://goo.gl/wUWSpv