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

Use the Kotlin Stdlib, Luke (GDG DevFest Vorone...

Use the Kotlin Stdlib, Luke (GDG DevFest Voronezh 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.

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

Sergey Ryabov

September 09, 2017
Tweet

More Decks by Sergey Ryabov

Other Decks in Programming

Transcript

  1. val starWars = Movie("Star Wars") starWars = Movie("Star Trek") var

    epicMovie = Movie("2012") epicMovie = Movie("The Day After Tomorrow")
  2. 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. data class Movie(val title: String, var airYear: Int? = null)

    fun releaseMovie(movie: Movie) { movie.airYear = today() }
  4. fun String.toInt(): Int = Integer.parseInt(this) public static final int toInt(@NotNull

    String $receiver) { return Integer.parseInt($receiver); }
  5. 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?
  6. 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) }
  7. 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()) }
  8. 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()) }
  9. 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()) }
  10. // 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)
  11. 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
  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")
  14. 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 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 }
  16. 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 }
  17. Map<String, String> headers = ArrayMap<String, String>() {{ this.put("User-Agent", userAgent); if

    (userManager.isLoggedIn) { this.put("Authorization", userManager.accessToken}); } }};
  18. 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) } }
  19. inline fun <T> T.apply(block: T.() -> Unit): T { block();

    return this } val headers = ArrayMap<String, String>().apply { put("User-Agent", userAgent) if (userManager.isLoggedIn) { put("Authorization", userManager.accessToken}) } }
  20. var user: User? if (user != null) { user.name }

    Error! Smart cast to ‘User’ is impossible, because ‘user’ is a mutable property that could have been changed by this time.
  21. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? if (user != null) { user.name } Error! Smart cast to ‘User’ is impossible, because ‘user’ is a mutable property that could have been changed by this time.
  22. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? user?.let { // ‘user’ is not null it.name }
  23. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? user?.let { // ‘user’ is not null and it.name }
  24. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) var user: User? user?.let { // ‘user’ is not null and ‘user’ was already read into local val it.name }
  25. inline fun <T, R> T.let(block: (T) -> R): R =

    block(this) getResponse()?.let { // ‘response’ was already read/delivered/calculated logResponse(it) saveData(parseData(it)) }
  26. 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() inline fun <T> T.takeIf(pred: (T) -> Boolean): T? = if (pred(this)) this else null inline fun <T> T.takeUnless(pred: (T) -> Boolean): T? = if (!pred(this)) this else null
  27. Map<Integer, String> int2Str = newMap(); <K,V> Map<K, V> newMap() {

    return new HashMap<K, V>(); } <T> T[] newArray(int size) { return new T[size]; }
  28. Map<Integer, String> int2Str = newMap(); <K,V> Map<K, V> newMap() {

    return new HashMap<K, V>(); } <T> T[] newArray(int size) { return new T[size]; }
  29. inline fun <reified T> arrayOfNulls(size: Int): Array<T?> = T[size] fun

    fill(dest: Array<Int?>) { // ... } fill(arrayOfNulls(10))
  30. 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]
  31. 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]
  32. fun byteArrayOf(vararg elements: Byte): ByteArray fun shortArrayOf(vararg elements: Short): ShortArray

    fun intArrayOf(vararg elements: Int): IntArray fun longArrayOf(vararg elements: Long): LongArray fun floatArrayOf(vararg elements: Float): FloatArray fun doubleArrayOf(vararg elements: Double): DoubleArray fun charArrayOf(vararg elements: Char): CharArray fun booleanArrayOf(vararg elements: Boolean): BooleanArray
  33. class Array<T> { inline constructor(size: Int, init: (index: Int) ->

    T) operator fun get(index: Int): T operator fun set(index: Int, value: T): Unit operator fun iterator(): Iterator<T> }
  34. class Array<T> { inline constructor(size: Int, init: (index: Int) ->

    T) operator fun get(index: Int): T operator fun set(index: Int, value: T): Unit operator fun iterator(): Iterator<T> } val arr = arrayOf("one", "one", "two") val one = arr[1] arr[0] = "zero" for (i in arr) { // ... }
  35. class Array<T> { inline constructor(size: Int, init: (index: Int) ->

    T) operator fun get(index: Int): T operator fun set(index: Int, value: T): Unit operator fun iterator(): Iterator<T> } // val arr = arrayOf("one", "one", "two") // val one = arr[1] // arr[0] = "zero" // for (i in arr) { // // ... // }
  36. 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>
  37. 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. 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> private fun getPetsRaw(): List<T>? { ... } fun getPets(): List<T> = getPetsRaw().orEmpty()
  39. 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>
  40. 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> // operator fun <T> get(i: Int): T val head: Note = notes[0] fun addNotes(newNotes: List<Note>) { this.notes += newNotes }
  41. typealias MCollection<T> = MutableCollection<T> typealias MList<T> = MutableList<T> typealias MMap<K,

    V> = MutableMap<K, V> typealias MIterable<T> = MutableIterable<T>
  42. 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. 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. 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: MCollection<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: MCollection<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: MCollection<in R>, R> Iterable<*>.filterIsInstanceTo(dest: C, klass: Class<R>): C inline fun <reified R, C: MCollection<in R>> Iterable<*>.filterIsInstanceTo(dest: C): C
  45. fun <T> MIterable<T>.removeAll(predicate: (T) -> Boolean): Boolean // filterNotInPlace() fun

    <T> MIterable<T>.retainAll(predicate: (T) -> Boolean): Boolean // filterInPlace() fun <T> MCollection<in T>.removeAll(Array<out T>|Iterable<T>|Sequence<T>): Boolean fun <T> MCollection<in T>.retainAll(Array<out T>|Iterable<T>|Sequence<T>): Boolean
  46. 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. fun <T: Comparable<T>> Iterable<T>.sorted(): List<T> fun <T: Comparable<T>> Iterable<T>.sortedDescending(): List<T>

    fun <T: Comparable<T>> MList<T>.sort(): Unit fun <T: Comparable<T>> MList<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>> MList<T>.sortBy(selector: (T) -> R?): Unit inline fun <T, R: Comparable<R>> MList<T>.sortByDescending(selector: (T) -> R?): Unit fun <T> Iterable<T>.sortedWith(comparator: Comparator<in T>): List<T> fun <T> MList<T>.sortWith(comparator: Comparator<in T>): Unit
  48. 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. 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: MMap<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. 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: MCollection<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: MCollection<in R>> Iterable<T>. mapNotNullTo(dest: C, transform: (T) -> R?): C mapIndexedNotNullTo(dest: C, transform: (index: Int, T) -> R?): C
  51. 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: MCollection<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: MMap<in K, MList<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. 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. 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. 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. 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. fun <T, C: MCollection<in T>> Iterable<T>.toCollection(dest: C): C fun <T>

    Iterable<T>.toList(): List<T> fun <T> Iterable<T>.toMutableList(): MList<T> fun <T> Iterable<T>.toSet(): Set<T> fun <T> Iterable<T>.toMutableSet(): MSet<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>
  57. 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)
  58. 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) getMovies()
  59. 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) getMovies() .filter { it.airDate > user.birthday }
  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) getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies }
  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) getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre }
  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) 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 }) }
  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) 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 }
  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) 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) }
  65. 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) }
  66. 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" }
  67. inline infix fun <T> Array<out T>.contentDeepEquals(other: Array<out T>): Boolean inline

    fun <T> Array<out T>.contentDeepHashCode(): Int inline fun <T> Array<out T>.contentDeepToString(): String inline fun <T> Array<T>.copyOf([newSize: Int]): Array<T> inline fun <T> Array<T>.copyOfRange(fromIndex: Int, toIndex: Int): Array<T> fun IntArray.toTypedArray(): Array<Int> fun Array<out Int>.toIntArray(): IntArray
  68. 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>
  69. fun genFibonacciSequence(): Sequence<Int> = generateSequence(0 to 1) { (prev, next)

    -> next to (prev + next) }.map { (next, _) -> next } genFibonacciSequence() .takeWhile { it < 100 } .forEach(::println)
  70. 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
  71. 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) }
  72. getMovies() .filter { it.airDate > jorah.birthday } .filter { it.title

    in jorah.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) }
  73. getMovies() .asSequence() .filter { it.airDate > jorah.birthday } .filter {

    it.title in jorah.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) }
  74. getMovies() .asSequence() .filter { it.airDate > jorah.birthday } .filter {

    it.title in jorah.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) }
  75. 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>
  76. 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
  77. 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>
  78. 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 }
  79. 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.
  80. 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 }
  81. 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 }
  82. 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 }
  83. fun <K, V> Map<K, V>. withDefault(defaultValue: (key: K) -> V):

    Map<K, V> fun <K, V> MutableMap<K, V>. withDefault(defaultValue: (key: K) -> V): MutableMap<K, V> Warning! Does not change Map.get() semantics! Use Map.getValue() fun <K, V> Map<K, V>.getValue(key: K): V
  84. 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 }
  85. 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 }
  86. 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>
  87. fun wordCount(list: List<String>): Map<String, Int> { return list .groupingBy {

    it } .aggregate { key, acc, elem, first -> (acc ?: 0) + 1 } }
  88. 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>
  89. 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 }
  90. 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>
  91. 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>
  92. 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>
  93. 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>
  94. 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)
  95. 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 } }
  96. 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 } }
  97. 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 } }
  98. fun String.capitalize(): String fun String.decapitalize(): String fun CharSequence.isBlank(): Boolean inline

    fun CharSequence?.isNullOrBlank(): Boolean // Farewell TextUtils.isEmpty() inline fun CharSequence?.isNullOrEmpty(): Boolean 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>
  99. 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 }
  100. 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
  101. 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
  102. 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
  103. 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
  104. val wordCount = File("shakespeare.txt").useLines { it.flatMap { it.splitToSequence(' ', ',',

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

    '.', '!', '?') } .map { it.toLowerCase() } .groupingBy { it } .eachCount() }
  106. 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
  107. 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
  108. inline fun <T> Lock.withLock(action: () -> T): T inline fun

    <T> ReentrantReadWriteLock.read(action: () -> T): T inline fun <T> ReentrantReadWriteLock.write(action: () -> T): T
  109. 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 rl = readLock() val readCount = if (writeHoldCount == 0) readHoldCount else 0 repeat(readCount) { rl.unlock() } val wl = writeLock() wl.lock() try { return action() } finally { repeat(readCount) { rl.lock() } wl.unlock() } }
  110. 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")
  111. 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"); } }
  112. inline fun measureNanoTime(block: () -> Unit) : Long inline fun

    measureTimeMillis(block: () -> Unit) : Long
  113. inline fun measureNanoTime(block: () -> Unit) : Long inline fun

    measureTimeMillis(block: () -> Unit) : Long val saveTime = measureNanoTime { saveToDb(entity) } println("Saving is soo sloow ${saveTime}ns")
  114. • No big inline method bodies • Public API in

    inline functions • Reified functions are not present in bytecode • Eager collections processing functions • Use Sequence • “as”/”to” prefix convention • Ranges optimisations
  115. • 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, 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