Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

val title = "GDG DevFest" val airDate: Date? = null

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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")

Slide 5

Slide 5 text

class Movie

Slide 6

Slide 6 text

class Movie(val title: String) println(movie.title)

Slide 7

Slide 7 text

class Movie(val title: String, var airYear: Int? = null)

Slide 8

Slide 8 text

data class Movie(val title: String, var airYear: Int? = null)

Slide 9

Slide 9 text

data class Movie(val title: String, var airYear: Int? = null) fun releaseMovie(movie: Movie) { movie.airYear = today() }

Slide 10

Slide 10 text

fun map(list: List, mapper: (T) -> V): List

Slide 11

Slide 11 text

fun map(list: List, mapper: (T) -> V): List

Slide 12

Slide 12 text

fun String.toInt(): Int = Integer.parseInt(this)

Slide 13

Slide 13 text

fun String.toInt(): Int = Integer.parseInt(this) public static final int toInt(@NotNull String $receiver) { return Integer.parseInt($receiver); }

Slide 14

Slide 14 text

inline fun String.toInt(): Int = Integer.parseInt(this)

Slide 15

Slide 15 text

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?

Slide 16

Slide 16 text

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) }

Slide 17

Slide 17 text

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()) }

Slide 18

Slide 18 text

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()) }

Slide 19

Slide 19 text

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()) }

Slide 20

Slide 20 text

// 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)

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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")

Slide 24

Slide 24 text

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 }

Slide 25

Slide 25 text

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 }

Slide 26

Slide 26 text

for (i in 5432) println(i)

Slide 27

Slide 27 text

for (i in 5432) println(i) operator fun Int.iterator(): MyType = MyType(this)

Slide 28

Slide 28 text

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 }

Slide 29

Slide 29 text

for (i in 5432) println(i) // 5, 4, 3, 2

Slide 30

Slide 30 text

Map headers = ArrayMap() {{ this.put("User-Agent", userAgent); if (userManager.isLoggedIn) { this.put("Authorization", userManager.accessToken}); } }};

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

var user: User? if (user != null) { user.name }

Slide 34

Slide 34 text

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.

Slide 35

Slide 35 text

inline fun 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.

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

inline fun 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 }

Slide 39

Slide 39 text

inline fun T.let(block: (T) -> R): R = block(this) getResponse()?.let { // ‘response’ was already read/delivered/calculated logResponse(it) saveData(parseData(it)) }

Slide 40

Slide 40 text

inline fun T.apply(block: T.() -> Unit): T { block(); return this } inline fun T.also(block: (T) -> Unit): T { block(this); return this } inline fun with(receiver: T, block: T.() -> R): R = receiver.block() inline fun T.let(block: (T) -> R): R = block(this) inline fun T.run(block: T.() -> R): R = block() inline fun run(block: () -> R): R = block() inline fun T.takeIf(pred: (T) -> Boolean): T? = if (pred(this)) this else null inline fun T.takeUnless(pred: (T) -> Boolean): T? = if (!pred(this)) this else null

Slide 41

Slide 41 text

Map int2Str = new HashMap();

Slide 42

Slide 42 text

Map int2Str = newMap(); Map newMap() { return new HashMap(); }

Slide 43

Slide 43 text

Map int2Str = newMap(); Map newMap() { return new HashMap(); } T[] newArray(int size) { return new T[size]; }

Slide 44

Slide 44 text

Map int2Str = newMap(); Map newMap() { return new HashMap(); } T[] newArray(int size) { return new T[size]; }

Slide 45

Slide 45 text

fun arrayOfNulls(size: Int): Array = T[size]

Slide 46

Slide 46 text

inline fun arrayOfNulls(size: Int): Array = T[size] fun fill(dest: Array) { // ... } fill(arrayOfNulls(10))

Slide 47

Slide 47 text

inline fun arrayOfNulls(size: Int): Array = T[size] inline fun arrayOf(vararg elements: T): Array = T[] { elements } inline fun emptyArray(): Array = T[0]

Slide 48

Slide 48 text

inline fun arrayOfNulls(size: Int): Array // = T[size] inline fun arrayOf(vararg elements: T): Array // = T[] { elements } inline fun emptyArray(): Array // = T[0]

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

class Array { 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 }

Slide 51

Slide 51 text

class Array { 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 } val arr = arrayOf("one", "one", "two") val one = arr[1] arr[0] = "zero" for (i in arr) { // ... }

Slide 52

Slide 52 text

class Array { 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 } // val arr = arrayOf("one", "one", "two") // val one = arr[1] // arr[0] = "zero" // for (i in arr) { // // ... // }

Slide 53

Slide 53 text

fun emptyList(): List = EmptyList fun listOf(element: T): List = Collections.singletonList(element) fun listOf([vararg elements: T]): List fun mutableListOf([vararg elements: T]): MutableList // ArrayList fun arrayListOf([vararg elements: T]): ArrayList fun listOfNotNull(element: T?): List fun listOfNotNull(vararg elements: T?): List inline fun List(size: Int, init: (index: Int) -> T): List inline fun MutableList(size: Int, init: (index: Int) -> T): MutableList

Slide 54

Slide 54 text

val List.lastIndex: Int get() = this.size - 1 inline fun Collection?.orEmpty(): Collection inline fun List?.orEmpty(): List

Slide 55

Slide 55 text

val List.lastIndex: Int get() = this.size - 1 inline fun Collection?.orEmpty(): Collection inline fun List?.orEmpty(): List private fun getPetsRaw(): List? { ... } fun getPets(): List = getPetsRaw().orEmpty()

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

inline operator fun List.component1(): T inline operator fun List.component5(): T operator fun Iterable.contains(element: T): Boolean operator fun Collection.plus(T|Array|Iterable|Sequence): List operator fun Iterable.plus(T|Array|Iterable|Sequence): List operator fun Iterable.minus(T|Array|Iterable|Sequence): List // operator fun get(i: Int): T val head: Note = notes[0] fun addNotes(newNotes: List) { this.notes += newNotes }

Slide 58

Slide 58 text

typealias MCollection = MutableCollection typealias MList = MutableList typealias MMap = MutableMap typealias MIterable = MutableIterable

Slide 59

Slide 59 text

inline fun Iterable.first([predicate: (T) -> Boolean]): T inline fun Iterable.last([predicate: (T) -> Boolean]): T inline fun Iterable.firstOrNull([predicate: (T) -> Boolean]): T? inline fun Iterable.lastOrNull([predicate: (T) -> Boolean]): T? inline fun Iterable.find(predicate: (T) -> Boolean): T? // = firstOrNull() inline fun Iterable.findLast(predicate: (T) -> Boolean): T? // = lastOrNull() inline fun Iterable.single([predicate: (T) -> Boolean]): T inline fun Iterable.singleOrNull([predicate: (T) -> Boolean]): T

Slide 60

Slide 60 text

fun Iterable.indexOf(element: T): Int fun Iterable.lastIndexOf(element: T): Int inline fun Iterable.indexOfFirst(predicate: (T) -> Boolean): Int inline fun Iterable.indexOfLast(predicate: (T) -> Boolean): Int fun List.binarySearch([from: Int, to: Int,] comparison: (T) -> Int): Int fun > List.binarySearch(elem: T?, [from: Int, to: Int]): Int fun List. binarySearch(elem: T, comparator: Comparator, [from: Int, to: Int]): Int inline fun > List. binarySearchBy(key: K?, [from: Int, to: Int,] selector: (T) -> K?): Int

Slide 61

Slide 61 text

inline fun Iterable.filter(predicate: (T) -> Boolean): List inline fun Iterable.filterIndexed(predicate: (index: Int, T) -> Boolean): List inline fun Iterable.filterNot(predicate: (T) -> Boolean): List fun Iterable.filterNotNull(): List inline fun > Iterable. filterTo(dest: C, predicate: (T) -> Boolean): C filterIndexedTo(dest: C, predicate: (index: Int, T) -> Boolean): C filterNotTo(dest: C, predicate: (T) -> Boolean): C fun , T : Any> Iterable.filterNotNullTo(dest: C): C fun Iterable<*>.filterIsInstance(klass: Class): List inline fun Iterable<*>.filterIsInstance(): List fun , R> Iterable<*>.filterIsInstanceTo(dest: C, klass: Class): C inline fun > Iterable<*>.filterIsInstanceTo(dest: C): C

Slide 62

Slide 62 text

fun MIterable.removeAll(predicate: (T) -> Boolean): Boolean // filterNotInPlace() fun MIterable.retainAll(predicate: (T) -> Boolean): Boolean // filterInPlace() fun MCollection.removeAll(Array|Iterable|Sequence): Boolean fun MCollection.retainAll(Array|Iterable|Sequence): Boolean

Slide 63

Slide 63 text

fun Iterable.take(n: Int): List fun List.takeLast(n: Int): List inline fun Iterable.takeWhile(predicate: (T) -> Boolean): List inline fun List.takeLastWhile(predicate: (T) -> Boolean): List fun Iterable.drop(n: Int): List fun List.dropLast(n: Int): List inline fun Iterable.dropWhile(predicate: (T) -> Boolean): List inline fun List.dropLastWhile(predicate: (T) -> Boolean): List

Slide 64

Slide 64 text

fun > Iterable.sorted(): List fun > Iterable.sortedDescending(): List fun > MList.sort(): Unit fun > MList.sortDescending(): Unit inline fun > Iterable.sortedBy(selector: (T) -> R?): List inline fun > Iterable.sortedByDescending(selector: (T) -> R?): List inline fun > MList.sortBy(selector: (T) -> R?): Unit inline fun > MList.sortByDescending(selector: (T) -> R?): Unit fun Iterable.sortedWith(comparator: Comparator): List fun MList.sortWith(comparator: Comparator): Unit

Slide 65

Slide 65 text

fun Iterable.reversed(): List fun MutableList.reverse(): Unit fun List.asReversed(): List fun MutableList.asReversed(): MutableList fun List.slice(indices: IntRange): List fun List.slice(indices: Iterable): List

Slide 66

Slide 66 text

inline fun Iterable. associate(transform: (T) -> Pair): Map associateBy(keySelector: (T) -> K, [valueTransform: (T) -> V]): Map inline fun > Iterable. associateTo(dest: M, transform: (T) -> Pair): M associateByTo(dest: M, keySelector: (T) -> K, [valueTransform: (T) -> V]): M

Slide 67

Slide 67 text

inline fun Iterable. map(transform: (T) -> R): List mapIndexed(transform: (index: Int, T) -> R): List inline fun Iterable. mapNotNull(transform: (T) -> R?): List mapIndexedNotNull(transform: (index: Int, T) -> R?): List inline fun > Iterable. mapTo(dest: C, transform: (T) -> R): C mapIndexedTo(dest: C, transform: (index: Int, T) -> R): C inline fun > Iterable. mapNotNullTo(dest: C, transform: (T) -> R?): C mapIndexedNotNullTo(dest: C, transform: (index: Int, T) -> R?): C

Slide 68

Slide 68 text

inline fun Iterable.forEach(action: (T) -> Unit): Unit inline fun Iterable.forEachIndexed(action: (index: Int, T) -> Unit): Unit inline fun > C.onEach(action: (T) -> Unit): C inline fun Iterable.flatMap(transform: (T) -> Iterable): List inline fun > Iterable. flatMapTo(dest: C, transform: (T) -> Iterable): C inline fun Iterable. groupBy(keySelector: (T) -> K, [valueTransform: (T) -> V]): Map> inline fun >> Iterable. groupByTo(dest: M, keySelector: (T) -> K, [valueTransform: (T) -> V]): M inline fun Iterable.groupingBy(keySelector: (T) -> K): Grouping

Slide 69

Slide 69 text

fun Iterable.distinct(): List inline fun Iterable.distinctBy(selector: (T) -> K): List fun Iterable>.flatten(): List infix fun Iterable.zip(Array|Iterable): List> inline fun Iterable. zip(Array|Iterable, transform: (a: T, b: R) -> V): List fun Iterable>.unzip(): Pair, List> inline fun Iterable.partition(predicate: (T) -> Boolean): Pair, List> infix fun Iterable.intersect(other: Iterable): Set infix fun Iterable.subtract(other: Iterable): Set infix fun Iterable.union(other: Iterable): Set

Slide 70

Slide 70 text

fun Iterable.average(): Double fun Iterable.sum(): Int inline fun Iterable.sumBy(selector: (T) -> Int): Int inline fun Iterable.sumByDouble(selector: (T) -> Double): Double inline fun Iterable.count([predicate: (T) -> Boolean]): Int fun > Iterable.max(): T? fun > Iterable.min(): T? inline fun > Iterable.maxBy(selector: (T) -> R): T? inline fun > Iterable.minBy(selector: (T) -> R): T? fun Iterable.maxWith(comparator: Comparator): T? fun Iterable.minWith(comparator: Comparator): T? inline fun Iterable.all(predicate: (T) -> Boolean): Boolean inline fun Iterable.any([predicate: (T) -> Boolean]): Boolean inline fun Iterable.none([predicate: (T) -> Boolean]): Boolean

Slide 71

Slide 71 text

inline fun Iterable. fold(initial: R, operation: (acc: R, T) -> R): R foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R inline fun List. foldRight(initial: R, operation: (T, acc: R) -> R): R foldRightIndexed(initial: R, operation: (index: Int, T, acc: R) -> R): R inline fun Iterable. reduce(operation: (acc: S, T) -> S): S reduceIndexed(operation: (index: Int, acc: S, T) -> S): S inline fun List. reduceRight(operation: (T, acc: S) -> S): S reduceRightIndexed(operation: (index: Int, T, acc: S) -> S): S

Slide 72

Slide 72 text

fun Iterable.joinToString( separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String fun Iterable.joinTo( buffer: A, sep: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A

Slide 73

Slide 73 text

fun > Iterable.toCollection(dest: C): C fun Iterable.toList(): List fun Iterable.toMutableList(): MList fun Iterable.toSet(): Set fun Iterable.toMutableSet(): MSet fun Iterable.toHashSet(): HashSet fun > Iterable.toSortedSet([comparator: Comparator]): SortedSet inline fun Collection.toTypedArray(): Array inline fun Iterable.asIterable(): Iterable fun Iterable.asSequence(): Sequence

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

data class User(val birthday: Date, val movies: List) data class Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) getMovies()

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

data class User(val birthday: Date, val movies: List) 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 }

Slide 79

Slide 79 text

data class User(val birthday: Date, val movies: List) 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 }

Slide 80

Slide 80 text

data class User(val birthday: Date, val movies: List) 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 }) }

Slide 81

Slide 81 text

data class User(val birthday: Date, val movies: List) 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 }

Slide 82

Slide 82 text

data class User(val birthday: Date, val movies: List) 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) }

Slide 83

Slide 83 text

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) }

Slide 84

Slide 84 text

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" }

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

inline infix fun Array.contentDeepEquals(other: Array): Boolean inline fun Array.contentDeepHashCode(): Int inline fun Array.contentDeepToString(): String inline fun Array.copyOf([newSize: Int]): Array inline fun Array.copyOfRange(fromIndex: Int, toIndex: Int): Array fun IntArray.toTypedArray(): Array fun Array.toIntArray(): IntArray

Slide 87

Slide 87 text

fun emptySequence(): Sequence = EmptySequence fun sequenceOf(vararg elements: T): Sequence fun generateSequence(nextFunction: () -> T?): Sequence generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence generateSequence(seedFunction: () -> T?, nextFunction: (T) -> T?): Sequence inline fun Sequence(iterator: () -> Iterator): Sequence fun Sequence.constrainOnce(): Sequence

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

fun genFibonacciSequence(): Sequence = 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

Slide 91

Slide 91 text

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) }

Slide 92

Slide 92 text

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) }

Slide 93

Slide 93 text

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) }

Slide 94

Slide 94 text

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) }

Slide 95

Slide 95 text

fun emptySet(): Set = EmptySet fun setOf(element: T): Set = Collections.singleton(element) fun setOf([vararg elements: T]): Set fun mutableSetOf([vararg elements: T]): MutableSet // LinkedHashSet fun hashSetOf([vararg elements: T]): HashSet fun linkedSetOf([vararg elements: T]): LinkedHashSet fun sortedSetOf([comparator: Comparator,] vararg elements: T): TreeSet

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

inline fun Map. filterKeys(predicate: (K) -> Boolean): Map filterValues(predicate: (V) -> Boolean): Map inline fun Map. mapKeys(transform: (Map.Entry) -> R): Map mapValues(transform: (Map.Entry) -> R): Map

Slide 98

Slide 98 text

fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item] + 1 } return map }

Slide 99

Slide 99 text

fun wordCount(list: List): Map { val map = mutableMapOf() 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.

Slide 100

Slide 100 text

fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item]!! + 1 } return map }

Slide 101

Slide 101 text

fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { map[item] = (map[item] ?: 0) + 1 } return map }

Slide 102

Slide 102 text

fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { map[item] = map.getOrElse(item) { 0 } + 1 } return map }

Slide 103

Slide 103 text

fun Map. withDefault(defaultValue: (key: K) -> V): Map fun MutableMap. withDefault(defaultValue: (key: K) -> V): MutableMap Warning! Does not change Map.get() semantics! Use Map.getValue() fun Map.getValue(key: K): V

Slide 104

Slide 104 text

fun wordCount(list: List): Map { val map = mutableMapOf().withDefault { 0 } for (item in list) { map[item] = map.getValue(item) + 1 } return map }

Slide 105

Slide 105 text

inline fun Iterable.groupingBy(keySelector: (T) -> K): Grouping

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

inline fun Iterable.groupingBy(keySelector: (T) -> K): Grouping interface Grouping { fun sourceIterator(): Iterator fun keyOf(element: T): K } inline fun Grouping. aggregate(op: (key: K, accumulator: R?, elem: T, first: Boolean) -> R): Map

Slide 108

Slide 108 text

fun wordCount(list: List): Map { return list .groupingBy { it } .aggregate { key, acc, elem, first -> (acc ?: 0) + 1 } }

Slide 109

Slide 109 text

fun wordCount(list: List): Map = list.groupingBy { it } .aggregate { _, acc, _, _ -> (acc ?: 0) + 1 }

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

fun wordCount(list: List): Map = list.groupingBy { it }.eachCount() fun Grouping.eachCount(): Map

Slide 112

Slide 112 text

fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item]!! + 1 } return map }

Slide 113

Slide 113 text

inline fun Grouping. fold(initialValue: R, operation: (accumulator: R, element: T) -> R): Map fold(initialValueSelector: (key: K, element: T) -> R, operation: (key: K, accumulator: R, element: T) -> R): Map inline fun Grouping. reduce(operation: (key: K, accumulator: S, element: T) -> S): Map

Slide 114

Slide 114 text

fun > maxOf(a: T, b: T, [c: T]): T fun > minOf(a: T, b: T, [c: T]): T // + variants for primitive numbers inline fun > nullsFirst(): Comparator inline fun > nullsLast(): Comparator fun nullsFirst(comparator: Comparator): Comparator fun nullsLast(comparator: Comparator): Comparator fun > naturalOrder(): Comparator fun > reverseOrder(): Comparator fun Comparator.reversed(): Comparator

Slide 115

Slide 115 text

fun compareBy(vararg selectors: (T) -> Comparable<*>?): Comparator inline fun compareBy(selector: (T) -> Comparable<*>?): Comparator inline fun compareBy(Comparator, selector: (T) -> K): Comparator

Slide 116

Slide 116 text

inline fun Comparator. thenComparator(comparison: (a: T, b: T) -> Int): Comparator thenBy(selector: (T) -> Comparable<*>?): Comparator thenByDescending(selector: (T) -> Comparable<*>?): Comparator inline fun Comparator. thenBy(Comparator, selector: (T) -> K): Comparator thenByDescending(Comparator, selector: (T) -> K): Comparator infix fun Comparator. then(comparator: Comparator): Comparator thenDescending(comparator: Comparator): Comparator

Slide 117

Slide 117 text

data class Movie(val title: String, val airYear: Int, val posterUrl: String, val likesCount: Int, val genre: Genre, val actors: List) enum class Genre { COMEDY, ACTION, DRAMA, DOCUMENTARY } getMovies() .sortedWith(movieComparator) .filterNot { it.title in user.movies } .take(100)

Slide 118

Slide 118 text

val movieComparator = compareBy()

Slide 119

Slide 119 text

val movieComparator = compareBy({ it.airYear })

Slide 120

Slide 120 text

val movieComparator = compareBy({ it.airYear }, { it.likesCount })

Slide 121

Slide 121 text

val movieComparator = compareBy(Movie::airYear, Movie::likesCount)

Slide 122

Slide 122 text

val movieComparator = compareBy(Movie::airYear, Movie::likesCount) .thenByDescending { it.actors.size }

Slide 123

Slide 123 text

val movieComparator = compareBy(Movie::airYear) .thenBy(Movie::likesCount) .thenByDescending { it.actors.size }

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

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 fun CharSequence.lineSequence(): Sequence

Slide 128

Slide 128 text

inline fun T.use(block: (T) -> R): R inline fun T.use(block: (T) -> R): R fun InputStream.readLines(): List = BufferedReader(InputStreamReader(this)).use { val lines = arrayListOf() var line = it.readLine() while (line != null) { lines += line line = it.readLine() } lines }

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

inline fun Reader.buffered([bufferSize: Int]): BufferedReader inline fun Writer.buffered([bufferSize: Int]): BufferedWriter fun Reader.readText(): String fun Reader.readLines(): List fun BufferedReader.lineSequence(): Sequence inline fun Reader.useLines(block: (Sequence) -> T): T fun Reader.forEachLine(action: (String) -> Unit): Unit fun Reader.copyTo(out: Writer, [bufferSize: Int]): Long

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

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 inline fun File.useLines([charset: Charset], block: (Sequence) -> T): T fun File.forEachLine([charset: Charset], action: (String) -> Unit): Unit fun File.forEachBlock([blockSize: Int,] action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

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

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

inline fun Lock.withLock(action: () -> T): T inline fun ReentrantReadWriteLock.read(action: () -> T): T inline fun ReentrantReadWriteLock.write(action: () -> T): T

Slide 139

Slide 139 text

inline fun Lock.withLock(action: () -> T): T inline fun ReentrantReadWriteLock.read(action: () -> T): T inline fun 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() } }

Slide 140

Slide 140 text

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")

Slide 141

Slide 141 text

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"); } }

Slide 142

Slide 142 text

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

Slide 143

Slide 143 text

inline fun measureNanoTime(block: () -> Unit) : Long inline fun measureTimeMillis(block: () -> Unit) : Long val saveTime = measureNanoTime { saveToDb(entity) } println("Saving is soo sloow ${saveTime}ns")

Slide 144

Slide 144 text

fun Stream.toList(): List fun Stream.asSequence(): Sequence fun Sequence.asStream(): Stream

Slide 145

Slide 145 text

● 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

Slide 146

Slide 146 text

● 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

Slide 147

Slide 147 text

Sergey Ryabov | twitter.com/colriot