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

Use the Kotlin Stdlib, Luke (with Anko) (GDG D...

Sergey Ryabov
September 30, 2017

Use the Kotlin Stdlib, Luke (with Anko) (GDG DevFest North 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. Finally, I'll go through the Anko's features hidden in its code.

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

Video: https://youtu.be/Hshrr_O31Xc

Sergey Ryabov

September 30, 2017
Tweet

More Decks by Sergey Ryabov

Other Decks in Programming

Transcript

  1. 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) }
  2. 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()) }
  3. 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()) }
  4. 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()) }
  5. 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)
  6. Extension Functions fun String.toInt(): Int = Integer.parseInt(this) public static final

    int toInt(@NotNull String $receiver) { return Integer.parseInt($receiver); }
  7. 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?
  8. 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
  9. 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
  10. 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
  11. 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
  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 val enormousNumber = BigInteger("12345678909876543210") * BigInteger("42") val enormousNumberV2 = -enormousNumber if (BigInteger("42") > BigInteger.TEN) { println("Welcome, Captain Obvious!") } Operator Overloading. Big Numbers
  13. 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 }
  14. 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 }
  15. 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 }
  16. 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); } }};
  17. 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) } }
  18. 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) } }
  19. var user: User? fun renderUser() { if (user != null)

    { nameView.text = user.name ageView.text = user.age } } Function Literals with Receiver
  20. 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
  21. var user: User? fun renderUser() { val usr = user

    if (usr != null) { nameView.text = usr.name ageView.text = usr.age } } Function Literals with Receiver
  22. 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
  23. 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
  24. 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
  25. 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
  26. 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
  27. 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
  28. 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)) } }
  29. 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()
  30. 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]; }
  31. 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]; }
  32. Reified Type Parameters inline fun <reified T> arrayOfNulls(size: Int): Array<T?>

    = T[size] fun fill(dest: Array<String?>) { // ... } fill(arrayOfNulls(10))
  33. 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]
  34. Kotlin features Stdlib is based on • Inline Functions •

    Extension Functions • Operator Overloading • Function Literals with Receiver • Reified type parameters
  35. 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>
  36. 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
  37. 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>
  38. 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>
  39. 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>(...)
  40. 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) { // ... }
  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> androidLanguagesList += "Kotlin"
  42. 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
  43. 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
  44. 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
  45. 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
  46. 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>
  47. 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
  48. 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>
  49. 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
  50. 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
  51. 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>
  52. 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>
  53. 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
  54. 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
  55. 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
  56. Here goes all the same stuff for Arrays, Sequences and

    CharSequences... ...if applicable
  57. 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>
  58. 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>
  59. 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>
  60. 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
  61. 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
  62. 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
  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) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } 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() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } 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 } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } 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 } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } 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 } .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
  68. 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
  69. 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
  70. 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
  71. fun genFibonacciSequence(): Sequence<Int> = generateSequence(0 to 1) { (prev, next)

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

    -> next to (prev + next) }.map { (next, _) -> next } genFibonacciSequence() .takeWhile { it < 100 } .forEach(::println) Sequences
  73. 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
  74. 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
  75. 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
  76. 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
  77. 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
  78. 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
  79. 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
  80. 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
  81. 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 }
  82. 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.
  83. 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 }
  84. 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 }
  85. 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 }
  86. 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
  87. 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 }
  88. 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
  89. 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>
  90. Grouping fun wordCount(list: List<String>): Map<String, Int> { return list .groupingBy

    { word -> word } .aggregate { key, acc, elem, first -> (acc ?: 0) + 1 } }
  91. 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>
  92. Grouping fun wordCount(list: List<String>): Map<String, Int> = list.groupingBy { it

    }.eachCount() fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int>
  93. 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 }
  94. 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>
  95. 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>
  96. 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>
  97. 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>
  98. 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)
  99. 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 } }
  100. 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 } }
  101. 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 } }
  102. 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>
  103. IO. Closeable inline fun <T : Closeable?, R> T.use(block: (T)

    -> R): R inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R
  104. 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 }
  105. 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
  106. 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
  107. 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
  108. 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
  109. IO. Files val wordCount = File("shakespeare.txt").useLines { it.flatMap { it.splitToSequence('

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

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

    ', ',', '.', '!', '?') } .map { it.toLowerCase() } .groupingBy { it } .eachCount() }
  112. 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
  113. 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
  114. 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")
  115. 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"); } }
  116. 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
  117. 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) }
  118. inline fun measureNanoTime(block: () -> Unit) : Long inline fun

    measureTimeMillis(block: () -> Unit) : Long Goodies. System
  119. 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
  120. 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>
  121. 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
  122. Anko. What I bet you know inline fun <reified T:

    Activity> Context. startActivity(vararg params: Pair<String, Any>) inline fun <reified T: Any> Context. intentFor(vararg params: Pair<String, Any?>): Intent
  123. Anko. What I bet you know inline fun <reified T:

    Activity> Context. startActivity(vararg params: Pair<String, Any>) inline fun <reified T: Any> Context. intentFor(vararg params: Pair<String, Any?>): Intent fun Context. toast(message: Int) longToast(message: Int)
  124. Anko. What I bet you know inline fun <reified T:

    Activity> Context. startActivity(vararg params: Pair<String, Any>) inline fun <reified T: Any> Context. intentFor(vararg params: Pair<String, Any?>): Intent fun Context. toast(message: Int) longToast(message: Int) val Context. alarmManager: AlarmManager audioManager: AudioManager connectivityManager: ConnectivityManager notificationManager: NotificationManager layoutInflater: LayoutInflater vibrator: Vibrator // ...
  125. Anko. What else? Collections inline fun <T> List<T>. forEachByIndex(f: (T)

    -> Unit) forEachWithIndex(f: (Int, T) -> Unit) // + Reversed
  126. Anko. What else? Collections inline fun <T> List<T>. forEachByIndex(f: (T)

    -> Unit) forEachWithIndex(f: (Int, T) -> Unit) // + Reversed
  127. Anko. What else? Collections inline fun <T> List<T>. forEachByIndex(f: (T)

    -> Unit) forEachWithIndex(f: (Int, T) -> Unit) // + Reversed inline fun <T> SparseArray<T>. forEach(action: (Int, T) -> Unit) asSequence(): Sequence<T>
  128. Anko. What else? ViewGroup Iteration fun ViewGroup. forEachChild(action: (View) ->

    Unit) forEachChildWithIndex(action: (Int, View) -> Unit) firstChild(predicate: (View) -> Boolean): View
  129. Anko. What else? ViewGroup Iteration fun ViewGroup. forEachChild(action: (View) ->

    Unit) forEachChildWithIndex(action: (Int, View) -> Unit) firstChild(predicate: (View) -> Boolean): View
  130. Anko. What else? ViewGroup Iteration fun ViewGroup. forEachChild(action: (View) ->

    Unit) forEachChildWithIndex(action: (Int, View) -> Unit) firstChild(predicate: (View) -> Boolean): View fun View.childrenRecursiveSequence(): Sequence<View>
  131. Anko. What else? Configuration Helpers doFromSdk(Build.VERSION_CODES.M) { window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR

    } configuration(uiMode = UiMode.CAR, nightMode = true) { schedulePlaySong("System Of A Down - Chop Suey!") }
  132. inline fun <reified T : View> Activity.find(@IdRes id: Int): T

    inline fun <reified T : View> Activity.findOptional(@IdRes id: Int): T? Anko. What else? ViewUtils
  133. inline fun <reified T : View> Activity.find(@IdRes id: Int): T

    inline fun <reified T : View> Activity.findOptional(@IdRes id: Int): T? val callBtn = findViewById(R.id.callBtn) as Button Anko. What else? ViewUtils
  134. inline fun <reified T : View> Activity.find(@IdRes id: Int): T

    inline fun <reified T : View> Activity.findOptional(@IdRes id: Int): T? val callBtn = findViewById(R.id.callBtn) as Button val callBtn = find<Button>(R.id.callBtn) Anko. What else? ViewUtils
  135. fun bundleOf(vararg params: Pair<String, Any>): Bundle fun showMap(location: LatLng, zoomLevel:

    Int) { val mapFragment = MapFragment().apply { arguments = bundleOf( EXTRA_LOCATION_KEY to location, EXTRA_ZOOM_KEY to zoomLevel ) } showFragment(mapFragment) } Anko. What else? Bundles
  136. fun <T: Fragment> T.withArguments(vararg params: Pair<String, Any>): T fun showMap(location:

    LatLng, zoomLevel: Int) { val mapFragment = MapFragment().withArguments( EXTRA_LOCATION_KEY to location, EXTRA_ZOOM_KEY to zoomLevel ) showFragment(mapFragment) } Anko. What else? Bundles
  137. 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