Kotlin
Need help with KotlinCheatSheet?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.
HugoMatilla

Description

A reference (copy/paste) of the the examples listed in http://try.kotlinlang.org/ in one single document. Good for fast search and quick reference

214 Stars 45 Forks 33 Commits 0 Opened issues

Services available

Need anything else?

Hello Kotlin

Hello World

We declare a package-level function main which returns Unit and takes an Array of strings as a parameter. Note that semicolons are optional.

    fun main(args: Array) {
        println("Hello, world!")
    }

Reading a name from the command line

Line 13 demonstrates string templates and array access. See this pages for details: http://kotlinlang.org/docs/reference/basic-types.html#strings http://kotlinlang.org/docs/reference/basic-types.html#arrays

    fun main(args: Array) {
        if (args.size == 0) {
            println("Please provide a name as a command-line argument")
            return
        }
        println("Hello, ${args[0]}!")
    }

Reading many names from the command line

Line 2 demonstrates the for-loop, that would have been called "enhanced" if there were any other for-loop in Kotlin. See http://kotlinlang.org/docs/reference/basic-syntax.html#using-a-for-loop

    fun main(args: Array) {
        for (name in args)
            println("Hello, $name!")

    for (i in args.indices)
        print(args[i])
}

When

In this example,

val
denotes a declaration of a read-only local variable, that is assigned an pattern matching expression. See http://kotlinlang.org/docs/reference/control-flow.html#when-expression
    fun main(args: Array) {
        val language = if (args.size == 0) "EN" else args[0]
        println(when (language) {
            "EN" -> "Hello!"
            "FR" -> "Salut!"
            "IT" -> "Ciao!"
            else -> "Sorry, I can't greet you in $language yet"
        })
    }

OOP Simple Class

Here we have a class with a primary constructor and a member function. Note that there's no

new
keyword used to create an object. See http://kotlinlang.org/docs/reference/classes.html#classes
    class Greeter(val name: String) {
        fun greet() {
            println("Hello, ${name}");
        }
    }

fun main(args: Array<string>) {
    Greeter(args[0]).greet()
}

Basics

if

if
is an expression, i.e. it returns a value. Therefore there is no ternary operator (condition ? then : else), because ordinary
if
works fine in this role. See http://kotlinlang.org/docs/reference/control-flow.html#if-expression
    fun main(args: Array) {
        println(max(Integer.parseInt(args[0]), Integer.parseInt(args[1])))
    }

fun max(a: Int, b: Int) = if (a &gt; b) a else b

Nullables

A reference must be explicitly marked as nullable to be able hold a null. See http://kotlinlang.org/docs/reference/null-safety.html#null-safety

    package multiplier

// Return null if str does not hold a number
fun parseInt(str: String): Int? {
    try {
        return Integer.parseInt(str)
    } catch (e: NumberFormatException) {
        println("One of the arguments isn't Int")
    }
    return null
}

fun main(args: Array<string>) {
    if (args.size &lt; 2) {
        println("No number supplied");
    } else {
        val x = parseInt(args[0])
        val y = parseInt(args[1])

        // We cannot say 'xy' now because they may hold nulls
        if (x != null &amp;&amp; y != null) {
            print(xy) // Now we can
        } else {
            println("One of the arguments is null")
    }
    }
}

is

The

is
operator checks if an expression is an instance of a type and more. If we is-checked an immutable local variable or property, there's no need to cast it explicitly to the is-checked type. See this pages for details: http://kotlinlang.org/docs/reference/classes.html#classes-and-inheritance http://kotlinlang.org/docs/reference/typecasts.html#smart-casts
    fun main(args: Array) {
        println(getStringLength("aaa"))
        println(getStringLength(1))
    }

fun getStringLength(obj: Any): Int? {
    if (obj is String)
        return obj.length // no cast to String is needed
    return null
}

while and do..while

See http://kotlinlang.org/docs/reference/control-flow.html#while-loops

    fun main(args: Array) {
    var i = 0
    while (i < args.size)
        println(args[i++])
}

Ranges

Check if a number lies within a range. Check if a number is out of range. Check if a collection contains an object. See http://kotlinlang.org/docs/reference/ranges.html#ranges

    fun main(args: Array) {
    val x = Integer.parseInt(args[0])
    //Check if a number lies within a range:
    val y = 10
    if (x in 1..y - 1)
        println("OK")

//Iterate over a range:
for (a in 1..5)
    print("${a} ")

//Check if a number is out of range:
println()
val array = arrayListOf<string>()
array.add("aaa")
array.add("bbb")
array.add("ccc")

if (x !in 0..array.size - 1)
    println("Out: array has only ${array.size} elements. x = ${x}")

//Check if a collection contains an object:
if ("aaa" in array) // collection.contains(obj) is called
    println("Yes: array contains aaa")

if ("ddd" in array) // collection.contains(obj) is called
    println("Yes: array contains ddd")
else
    println("No: array doesn't contains ddd")

}

Control flow when

See http://kotlinlang.org/docs/reference/control-flow.html#when-expression

    fun main(args: Array) {
    cases("Hello")
    cases(1)
    cases(System.currentTimeMillis())
    cases(MyClass())
    cases("hello")
}

fun cases(obj: Any) {
    when (obj) {
        1 -&gt; println("One")
        "Hello" -&gt; println("Greeting")
        is Long -&gt; println("Long")
        !is String -&gt; println("Not a string")
        else -&gt; println("Unknown")
    }
}

class MyClass() {
}

Multi-declarations and Data classes

Multi-declarations

This example introduces a concept that we call mutli-declarations. It creates multiple variable at once. Anything can be on the right-hand side of a mutli-declaration, as long as the required number of component functions can be called on it. See http://kotlinlang.org/docs/reference/multi-declarations.html#multi-declarations

    fun main(args: Array) {
        val pair = Pair(1, "one")

    val (num, name) = pair

    println("num = $num, name = $name")
}

class Pair<k v>(val first: K, val second: V) {
    operator fun component1(): K {
        return first
    }

    operator fun component2(): V {
        return second
    }
}

Data classes

Data class gets component functions, one for each property declared in the primary constructor, generated automatically, same for all the other goodies common for data toString(), equals(), hashCode() and copy(). See http://kotlinlang.org/docs/reference/data-classes.html#data-classes

    data class User(val name: String, val id: Int)

fun getUser(): User {
    return User("Alex", 1)
}

fun main(args: Array<string>) {
    val user = getUser()
    println("name = ${user.name}, id = ${user.id}")

    // or

    val (name, id) = getUser()
    println("name = $name, id = $id")

    // or

    println("name = ${getUser().component1()}, id = ${getUser().component2()}")
}

Data Maps

Kotlin Standart Library provide component functions for Map.Entry

    fun main(args: Array) {
        val map = hashMapOf()
        map.put("one", 1)
        map.put("two", 2)

    for ((key, value) in map) {
        println("key = $key, value = $value")
    }
}

Autogenerated Functions

Data class gets next functions, generated automatically: component functions, toString(), equals(), hashCode() and copy(). See http://kotlinlang.org/docs/reference/data-classes.html#data-classes

    data class User(val name: String, val id: Int)

fun main(args: Array<string>) {
    val user = User("Alex", 1)
    println(user) // toString()

    val secondUser = User("Alex", 1)
    val thirdUser = User("Max", 2)

    println("user == secondUser: ${user == secondUser}")
    println("user == thirdUser: ${user == thirdUser}")

    // copy() function
    println(user.copy())
    println(user.copy("Max"))
    println(user.copy(id = 2))
    println(user.copy("Max", 2))
}

Delegated properties

Custom Delegate

There's some new syntax: you can say

val 'property name': 'Type' by 'expression'
. The expression after by is the delegate, because get() and set() methods corresponding to the property will be delegated to it. Property delegates don't have to implement any interface, but they have to provide methods named get() and set() to be called.
    import kotlin.reflect.KProperty

class Example {
    var p: String by Delegate()

    override fun toString() = "Example Class"
}

class Delegate() {
): String {
        return "$thisRef, thank you for delegating '${prop.name}' to me!"
    }

, value: String) {
        println("$value has been assigned to ${prop.name} in $thisRef")
    }
}

fun main(args: Array<string>) {
    val e = Example()
    println(e.p)
    e.p = "NEW"
}

Lazy property

Delegates.lazy() is a function that returns a delegate that implements a lazy property: the first call to get() executes the lambda expression passed to lazy() as an argument and remembers the result, subsequent calls to get() simply return the remembered result. If you want thread safety, use blockingLazy() instead: it guarantees that the values will be computed only in one thread, and that all threads will see the same value.

    class LazySample {
        val lazy: String by lazy {
            println("computed!")
            "my lazy"
        }
    }

fun main(args: Array<string>) {
    val sample = LazySample()
    println("lazy = ${sample.lazy}")
    println("lazy = ${sample.lazy}")
}

Observable Property

The observable() function takes two arguments: initial value and a handler for modifications. The handler gets called every time we assign to

name
, it has three parameters: a property being assigned to, the old value and the new one. If you want to be able to veto the assignment, use vetoable() instead of observable().
    import kotlin.properties.Delegates

class User {
    var name: String by Delegates.observable("no name") {
        d, old, new -&gt;
        println("$old - $new")
    }
}

fun main(args: Array<string>) {
    val user = User()
    user.name = "Carl"
}

NotNull property

Users frequently ask what to do when you have a non-null var, but you don't have an appropriate value to assign to it in constructor (i.e. it must be assigned later)? You can't have an uninitialized non-abstract property in Kotlin. You could initialize it with null, bit then you'd have to check every time you access it. Now you have a delegate to handle this. If you read from this property before writing to it, it throws an exception, after the first assignment it works as expected.

    import kotlin.properties.Delegates

class User {
    var name: String by Delegates.notNull()

    fun init(name: String) {
        this.name = name
    }
}

fun main(args: Array<string>) {
    val user = User()
    // user.name -&gt; IllegalStateException
    user.init("Carl")
    println(user.name)
}

Properties in map

Properties stored in a map. This comes up a lot in applications like parsing JSON or doing other "dynamic" stuff. Delegates take values from this map (by the string keys - names of properties). Of course, you can have var's as well (add import kotlin.properties.setValue), that will modify the map upon assignment (note that you'd need MutableMap instead of read-only Map).

    import kotlin.properties.getValue

class User(val map: Map<string any>) {
    val name: String by map
    val age: Int     by map
}

fun main(args: Array<string>) {
    val user = User(mapOf(
            "name" to "John Doe",
            "age"  to 25
    ))

    println("name = ${user.name}, age = ${user.age}")
}

Callable references

Reference to a function

"Callable References" or "Feature Literals", i.e. an ability to pass named functions or properties as values. Users often ask "I have a foo() function, how do I pass it as an argument?". The answer is: "you prefix it with a

::
".
    fun main(args: Array) {
        val numbers = listOf(1, 2, 3)
        println(numbers.filter(::isOdd))
    }

fun isOdd(x: Int) = x % 2 != 0

Composition of functions

The composition function return a composition of two functions passed to it: compose(f, g) = f(g). Now, you can apply it to callable references.

    fun main(args: Array) {
        val oddLength = compose(::isOdd, ::length)
        val strings = listOf("a", "ab", "abc")
        println(strings.filter(oddLength))
    }

fun isOdd(x: Int) = x % 2 != 0
fun length(s: String) = s.length

fun <a b c> compose(f: (B) -&gt; C, g: (A) -&gt; B): (A) -&gt; C {
    return { x -&gt; f(g(x)) }
}

Longer Examples

99 Botles of Beer

This example implements the famous "99 Bottles of Beer" program See http://99-bottles-of-beer.net/ The point is to print out a song with the following lyrics: * The "99 bottles of beer" song * 99 bottles of beer on the wall, 99 bottles of beer. * Take one down, pass it around, 98 bottles of beer on the wall. * 98 bottles of beer on the wall, 98 bottles of beer. * Take one down, pass it around, 97 bottles of beer on the wall. * ... * 2 bottles of beer on the wall, 2 bottles of beer. * Take one down, pass it around, 1 bottle of beer on the wall. * 1 bottle of beer on the wall, 1 bottle of beer. * Take one down, pass it around, no more bottles of beer on the wall. * No more bottles of beer on the wall, no more bottles of beer. * Go to the store and buy some more, 99 bottles of beer on the wall.

Additionally, you can pass the desired initial number of bottles to use (rather than 99) as a command-line argument ``` kotlin

package bottles

fun main(args: Array) { if (args.isEmpty) { printBottles(99) } else { try { printBottles(Integer.parseInt(args[0])) } catch (e: NumberFormatException) { System.err.println("You have passed '${args[0]}' as a number of bottles, " + "but it is not a valid integer number") } } }

fun printBottles(bottleCount: Int) { if (bottleCount <= 0) { println("No bottles - no song") return }

println("The \"${bottlesOfBeer(bottleCount)}\" song\n")

var bottles = bottleCount
while (bottles &gt; 0) {
    val bottlesOfBeer = bottlesOfBeer(bottles)
    print("$bottlesOfBeer on the wall, $bottlesOfBeer.\nTake one down, pass it around, ")
    bottles--
    println("${bottlesOfBeer(bottles)} on the wall.\n")
}
println("No more bottles of beer on the wall, no more bottles of beer.\n" +
        "Go to the store and buy some more, ${bottlesOfBeer(bottleCount)} on the wall.")

}

fun bottlesOfBeer(count: Int): String = when (count) { 0 -> "no more bottles" 1 -> "1 bottle" else -> "$count bottles" } + " of beer"

An excerpt from the Standard Library

// This is an extension property, i.e. a property that is defined for the // type Array, but does not sit inside the class Array val Array.isEmpty: Boolean get() = size == 0

HTML Builder

This is an example of a Type-Safe Groovy-style Builder Builders are good for declaratively describing data in your code. In this example we show how to describe an HTML page in Kotlin. See this page for details: http://kotlinlang.org/docs/reference/type-safe-builders.html

``` kotlin

package html

fun main(args: Array<string>) {
    val result =
            html {
                head {
                    title { +"XML encoding with Kotlin" }
                }
                body {
                    h1 { +"XML encoding with Kotlin" }
                    p { +"this format can be used as an alternative markup to XML" }

                    // an element with attributes and text content
                    a(href = "http://jetbrains.com/kotlin") { +"Kotlin" }

                    // mixed content
                    p {
                        +"This is some"
                        b { +"mixed" }
                        +"text. For more see the"
                        a(href = "http://jetbrains.com/kotlin") { +"Kotlin" }
                        +"project"
                    }
                    p { +"some text" }

                    // content generated from command-line arguments
                    p {
                        +"Command line arguments were:"
                        ul {
                            for (arg in args)
                                li { +arg }
                        }
                    }
                }
            }
    println(result)
}

interface Element {
    fun render(builder: StringBuilder, indent: String)
}

class TextElement(val text: String) : Element {
    override fun render(builder: StringBuilder, indent: String) {
        builder.append("$indent$text\n")
    }
}

abstract class Tag(val name: String) : Element {
    val children = arrayListOf<element>()
    val attributes = hashMapOf<string string>()

    protected fun <t : element> initTag(tag: T, init: T.() -&gt; Unit): T {
        tag.init()
        children.add(tag)
        return tag
    }

    override fun render(builder: StringBuilder, indent: String) {
        builder.append("$indent\n")
        for (c in children) {
            c.render(builder, indent + "  ")
        }
        builder.append("$indent$name&gt;\n")
    }

    private fun renderAttributes(): String? {
        val builder = StringBuilder()
        for (a in attributes.keys) {
            builder.append(" $a=\"${attributes[a]}\"")
    }
        return builder.toString()
    }


    override fun toString(): String {
        val builder = StringBuilder()
        render(builder, "")
        return builder.toString()
    }
}

abstract class TagWithText(name: String) : Tag(name) {
    operator fun String.unaryPlus() {
        children.add(TextElement(this))
    }
}

class HTML() : TagWithText("html") {
    fun head(init: Head.() -&gt; Unit) = initTag(Head(), init)

    fun body(init: Body.() -&gt; Unit) = initTag(Body(), init)
}

class Head() : TagWithText("head") {
    fun title(init: Title.() -&gt; Unit) = initTag(Title(), init)
}

class Title() : TagWithText("title")

abstract class BodyTag(name: String) : TagWithText(name) {
    fun b(init: B.() -&gt; Unit) = initTag(B(), init)
    fun p(init: P.() -&gt; Unit) = initTag(P(), init)
    fun h1(init: H1.() -&gt; Unit) = initTag(H1(), init)
    fun ul(init: UL.() -&gt; Unit) = initTag(UL(), init)
    fun a(href: String, init: A.() -&gt; Unit) {
        val a = initTag(A(), init)
        a.href = href
    }
}

class Body() : BodyTag("body")
class UL() : BodyTag("ul") {
    fun li(init: LI.() -&gt; Unit) = initTag(LI(), init)
}

class B() : BodyTag("b")
class LI() : BodyTag("li")
class P() : BodyTag("p")
class H1() : BodyTag("h1")

class A() : BodyTag("a") {
    public var href: String
        get() = attributes["href"]!!
        set(value) {
            attributes["href"] = value
        }
}

fun html(init: HTML.() -&gt; Unit): HTML {
    val html = HTML()
    html.init()
    return html
}

Game of life

Ommitted

Maze

Ommitted

Problems

Sum

Your task is to implement the sum() function so that it computes the sum of all elements in the given array a.

    package sum

fun sum(a: IntArray): Int {
    var result=0
      for (number in a)
        result += number
    return result
}

indexOfMax

Your task is to implement the indexOfMax() function so that it returns the index of the largest element in the array, or null if the array is empty. ```kotlin

package maxindex

fun indexOfMax(a: IntArray): Int? { var maxNumber = Integer.MIN_VALUE var result = 0 if (a.size==0) return null else{ for (i in a.indices){ maxNumber = max(maxNumber,a[i]) if(maxNumber == a[i]) result = i } } return result } fun max(a: Int, b: Int) = if (a > b) a else b

## Runs

Any array may be viewed as a number of "runs" of equal numbers. For example, the following array has two runs: 1, 1, 1, 2, 2 Three 1's in a row form the first run, and two 2's form the second. This array has two runs of length one: 3, 4 And this one has five runs: 1, 0, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0
Your task is to implement the runs() function so that it returns the number of runs in the given array.

```kotlin

package runs

fun runs(a: IntArray): Int {
    if (a.size==0)
        return 0

    var runNumber =a[0]
    var result = 1

    for (number in a)
        if(runNumber != number){
            result ++
            runNumber = number
        }
    return result
}

Pairless

Think of a perfect world where everybody has a soulmate. Now, the real world is imperfect: there is exactly one number in the array that does not have a pair. A pair is an element with the same value.

For example in this array: 1, 2, 1, 2 every number has a pair, but in this one: 1, 1, 1 one of the ones is lonely.

Your task is to implement the findPairless() function so that it finds the lonely number and returns it. A hint: there's a solution that looks at each element only once and uses no data structures like collections or trees.

    package pairless

fun findPairless(a: IntArray): Int {
    val distinctElements = a.distinct()
    for (element in distinctElements){
        if(!a.count{it == element}.isEven())
           return element
    }
    return 0
}
fun Int.isEven() = this.mod(2) !=1

Canvas

Ommitted

Koans

joinOptions

    fun joinOptions(options: Collection) = options.joinToString(", ","[","]")

Default arguments

    fun foo(name: String, number: Int = 42, toUpperCase: Boolean = false) =
        (if (toUpperCase) name.toUpperCase() else name) + number

fun useFoo() = listOf(
        foo("a"),
        foo("b", number = 1),
        foo("c", toUpperCase = true),
        foo(name = "d", number = 2, toUpperCase = true)
)

Lambdas

    fun containsEven(collection: Collection): Boolean = collection.any { it.mod(2) == 0 }

Strings

    val s = "abc"
    val str = "$s.length is ${s.length}" // evaluates to "abc.length is 3"
    ...
    val month = "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)"
    fun getPattern() = """\d{2} ${month} \d{4}"""

Data classes

    data class Person (var name: String, var age: Int) 

fun getPeople(): List<person> {
    return listOf(Person("Alice", 29), Person("Bob", 31))
}

Nullable types

    fun sendMessageToClient(client: Client?, message: String?, mailer: Mailer){
            val mail = client?.personalInfo?.email ?: return
            if (message!=null)
                mailer.sendMessage(mail, message)
        }

class Client (val personalInfo: PersonalInfo?)
class PersonalInfo (val email: String?)
interface Mailer {fun sendMessage(email: String, message: String)}

Smart Cast

    fun eval(expr: Expr): Int =
        when (expr) {
            is Num -> expr.value
            is Sum -> eval(expr.left) + eval(expr.right) 
            else -> throw IllegalArgumentException("Unknown expression")
        }

interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr

Extension Functions

    fun Int.r(): RationalNumber = RationalNumber(this,1)
    fun Pair.r(): RationalNumber = RationalNumber(this.component1(),this.component2())

data class RationalNumber(val numerator: Int, val denominator: Int)

Object expressions

    import java.util.*

fun getList(): List<int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, object : Comparator<int> {
        override fun compare(x: Int, y: Int) = y - x
    })
    return arrayList
}

SAM conversions

    import java.util.*

fun getList(): List<int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, { x, y -&gt; y-x })
    return arrayList
}

Extension functions on collections

    fun getList(): List {
        return arrayListOf(1, 5, 2).sortedDescending()
    }

Conventions

Comparison

    data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable {
        override fun compareTo(other: MyDate) = when {
            year != other.year -> year - other.year
            month != other.month -> month - other.month
            else -> dayOfMonth - other.dayOfMonth
        }
}

In range

    class DateRange(val start: MyDate, val endInclusive: MyDate){
        operator fun contains(item: MyDate): Boolean = start <= item && item <= endInclusive
    }        


fun checkInRange(date: MyDate, first: MyDate, last: MyDate): Boolean {
    return date in DateRange(first, last)
}

    operator fun MyDate.rangeTo(other: MyDate) = DateRange(this, other)

class DateRange(override val start: MyDate, override val endInclusive: MyDate): ClosedRange<mydate> 

data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<mydate>{
    override fun compareTo(other: MyDate): Int{
        if(year != other.year) return year - other.year
        if(month != other.month) return month - other.month
        return dayOfMonth - other.dayOfMonth
    }
}

fun checkInRange(date: MyDate, first: MyDate, last: MyDate): Boolean {
    return date in first..last
}

For loop

    class DateRange(val start: MyDate, val end: MyDate): Iterable{
        override fun iterator(): Iterator = DateIterator(this)
    }

class DateIterator(val dateRange:DateRange) : Iterator<mydate> {
    var current: MyDate = dateRange.start
    override fun next(): MyDate {
        val result = current
        current = current.nextDay()
        return result
    }
    override fun hasNext(): Boolean = current &lt;= dateRange.end
}

fun iterateOverDateRange(firstDate: MyDate, secondDate: MyDate, handler: (MyDate) -&gt; Unit) {
    for (date in firstDate..secondDate) {
        handler(date)
    }
}

Operators overloading

    operator fun MyDate.plus(timeInterval: TimeInterval) = addTimeIntervals(timeInterval, 1)

class RepeatedTimeInterval(val timeInterval: TimeInterval, val number: Int)
operator fun TimeInterval.times(number: Int) = RepeatedTimeInterval(this, number)

operator fun MyDate.plus(timeIntervals: RepeatedTimeInterval) = addTimeIntervals(timeIntervals.timeInterval, timeIntervals.number)

Destructuring declarations

    data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int)

fun isLeapDay(date: MyDate): Boolean {

    val (year, month, dayOfMonth) = date

    // 29 February of a leap year
    return year % 4 == 0 &amp;&amp; month == 2 &amp;&amp; dayOfMonth == 29
}

Invoke

    class Invokable {
    public var numberOfInvocations: Int = 0
        private set
    operator public fun invoke(): Invokable {
        numberOfInvocations++
        return this  }
    }

fun invokeTwice(invokable: Invokable) = invokable()()

Collections

Introduction

Default collections in Kotlin are Java collections, but there are lots of useful extension functions for them. For example, operations that transform a collection to another one, starting with 'to':

toSet
or
toList
.
    data class Shop(val name: String, val customers: List)

data class Customer(val name: String, val city: City, val orders: List<order>) {
    override fun toString() = "$name from ${city.name}"
}

data class Order(val products: List<product>, val isDelivered: Boolean)

data class Product(val name: String, val price: Double) {
    override fun toString() = "'$name' for $price"
}

data class City(val name: String) {
    override fun toString() = name
}

    fun Shop.getSetOfCustomers(): Set = this.customers.toSet()

filter map

    val numbers = listOf(1, -1, 2)
    numbers.filter { it > 0 } == listOf(1, 2)
    numbers.map { it * it } == listOf(1, 1, 4)

// Return the set of cities the customers are from
fun Shop.getCitiesCustomersAreFrom(): Set<city> = customers.map {it.city}.toSet()

// Return a list of the customers who live in the given city
fun Shop.getCustomersFrom(city: City): List<customer> = this.customers.filter {it.city == city}

all, any count and find

    val numbers = listOf(-1, 0, 2)
    val isZero: (Int) -> Boolean = { it == 0 }
    numbers.any(isZero) == true
    numbers.all(isZero) == false
    numbers.count(isZero) == 1
    numbers.find { it > 0 } == 2

// Return true if all customers are from the given city
fun Shop.checkAllCustomersAreFrom(city: City): Boolean = customers.all{it.city== city}

// Return true if there is at least one customer from the given city
fun Shop.hasCustomerFrom(city: City): Boolean = customers.any{it.city== city}

// Return the number of customers from the given city
fun Shop.countCustomersFrom(city: City): Int = customers.count{it.city== city}

// Return a customer who lives in the given city, or null if there is none
fun Shop.findAnyCustomerFrom(city: City): Customer? = customers.find{it.city== city}

flatMap

    val result = listOf("abc", "12").flatMap { it.toCharList() }
    result == listOf('a', 'b', 'c', '1', '2')

// Return all products this customer has ordered
fun Customer.getOrderedProducts(): Set<product> = orders.flatMap{it.products}.toSet()

// Return all products that were ordered by at least one customer
fun Shop.getAllOrderedProducts(): Set<product> = customers.flatMap{it.getOrderedProducts()}.toSet()

max, min, maxBy and minBy

    listOf(1, 42, 4).max() == 42
    listOf("a", "ab").minBy { it.length } == "a"

// Return a customer whose order count is the highest among all customers
fun Shop.getCustomerWithMaximumNumberOfOrders(): Customer? = customers.maxBy {it.orders.size}

// Return the most expensive product which has been ordered
fun Customer.getMostExpensiveOrderedProduct(): Product? = orders.flatMap{it.products}.maxBy{it.price}

sort

    listOf("bbb", "a", "cc").sorted() == listOf("a", "bbb", "cc")
    listOf("bbb", "a", "cc").sortedBy { it.length } == listOf("a", "cc", "bbb")

// Return a list of customers, sorted by the ascending number of orders they made
fun Shop.getCustomersSortedByNumberOfOrders(): List<customer> = customers.sortedBy{it.orders.size}

sum

    listOf(1, 5, 3).sum() == 9
    listOf("a", "b", "cc").sumBy { it.length() } == 4

// Return the sum of prices of all products that a customer has ordered.
// Note: the customer may order the same product for several times.
fun Customer.getTotalOrderPrice(): Double = orders.flatMap{it.products}.sumByDouble{it.price}

groupBy

    val result = listOf("a", "b", "ba", "ccc", "ad").groupBy { it.length() }
    result == mapOf(1 to listOf("a", "b"), 2 to listOf("ba", "ad"), 3 to listOf("ccc"))

// Return a map of the customers living in each city
fun Shop.groupCustomersByCity(): Map<city list>&gt; = customers.groupBy{it.city}

partition

    val numbers = listOf(1, 3, -4, 2, -11)
    val (positive, negative) = numbers.partition { it > 0 }
    positive == listOf(1, 3, 2)
    negative == listOf(-4, -11)

// Return customers who have more undelivered orders than delivered
fun Shop.getCustomersWithMoreUndeliveredOrdersThanDelivered(): Set<customer> = customers.filter{
    val (delivered, undelivered) = it.orders.partition { it.isDelivered }
    undelivered.size &gt; delivered.size
}.toSet()

fold

    listOf(1, 2, 3, 4).fold(1, {
        partProduct, element ->
        element * partProduct
    }) == 24

fun Shop.getSetOfProductsOrderedByEveryCustomer(): Set<product> {
    val allProducts = customers.flatMap { it.orders.flatMap { it.products }}.toSet()
    return customers.fold(allProducts, {
        orderedByAll, customer -&gt;
        orderedByAll.intersect(customer.orders.flatMap { it.products }.toSet())
    })
}

Compound tasks

    fun Customer.getMostExpensiveDeliveredProduct(): Product? {
        return orders.filter { it.isDelivered }.flatMap { it.products }.maxBy { it.price }
    }

fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int {
    return customers.flatMap { it.getOrderedProductsList() }.count { it == product }
}

fun Customer.getOrderedProductsList(): List<product> {
    return orders.flatMap { it.products }
}

Get used to new style

    fun doSomethingStrangeWithCollection(collection: Collection): Collection? {

    val groupsByLength = collection. groupBy { s -&gt; s.length }

    val maximumSizeOfGroup = groupsByLength.values.map { group -&gt; group.size }.max()

    return groupsByLength.values.firstOrNull { group -&gt; group.size == maximumSizeOfGroup }
}

Properties

Properties

    class PropertyExample() {
        var counter = 0
        var propertyWithCounter: Int? = null
            set(v:Int?) {
                field = v
                counter++
            }
    }

Lazy property

    class LazyProperty(val initializer: () -> Int) {
    var value: Int? = null
    val lazy: Int
        get() {
            if (value == null) {
                value = initializer()
            }
            return value!!
        }
}

Delegates example

    class LazyProperty(val initializer: () -> Int) {
        val lazyValue: Int by lazy(initializer)
    }

Delegates how it works

class EffectiveDate<r> : ReadWriteProperty<r mydate> {

    var timeInMillis: Long? = null

    override fun getValue(thisRef: R, property: KProperty): MyDate = timeInMillis!!.toDate()

    override fun setValue(thisRef: R, property: KProperty, value: MyDate) {
        timeInMillis = value.toMillis()
    }
}

Extension function literals

A higher-order function is a function that takes functions as parameters, or returns a function. ```kotlin

fun task(): List {
    val isEven: Int.() -> Boolean = { this % 2 == 0 }
    val isOdd: Int.() -> Boolean = { this % 2 != 0 }

return listOf(42.isOdd(), 239.isOdd(), 294823098.isEven())

}

##

```kotlin

fun buildString(build: StringBuilder.() -&gt; Unit): String {
    val stringBuilder = StringBuilder()
    stringBuilder.build()
    return stringBuilder.toString()
}

val s = buildString {
    this.append("Numbers: ")
    for (i in 1..3) {
        // 'this' can be omitted
        append(i)
    }
}

s == "Numbers: 123"

---

import java.util.HashMap

fun <k v> buildMap(build: HashMap<k v>.() -&gt; Unit): Map<k v> {
    val map = HashMap<k v>()
    map.build()
    return map
}


fun usage(): Map<int string> {
    return buildMap {
        put(0, "0")
        for (i in 1..10) {
            put(i, "$i")
        }
    }
}

The function apply

    fun  T.myApply(f: T.() -> Unit): T { f(); return this } 

fun buildString(): String {
    return StringBuilder().myApply {
        append("Numbers: ")
        for (i in 1..10) {
            append(i)
        }
    }.toString()
}



fun buildMap(): Map<int string> {
    return hashMapOf<int string>().myApply {
        put(0, "0")
        for (i in 1..10) {
            put(i, "$i")
        }
    }
}

Html builder

    fun renderProductTable(): String {
        return html {
            table {
                tr (color = getTitleColor()) {
                    td {
                        text("Product")
                    }
                    td {
                        text("Price")
                    }
                    td {
                        text("Popularity")
                    }
                }
                val products = getProducts()
                for ((index, product) in products.withIndex()) {
                    tr {
                        td (color = getCellColor(index, 0)) {
                            text(product.description)
                        }
                        td (color = getCellColor(index, 1)) {
                            text(product.price)
                        }
                        td (color = getCellColor(index, 2)) {
                            text(product.popularity)
                        }
                    }
                }
            }
        }.toString()
    }

    Look at the questions below and give your answers

1. In the Kotlin code

tr {
    td {
        text("Product")
    }
    td {
        text("Popularity")
    }
}
'td' is:

a. special built-in syntactic construct

b. function declaration

c. function invocation

---------------------

2. In the Kotlin code

tr (color = "yellow") {
    td {
        text("Product")
    }
    td {
        text("Popularity")
    }
}
'color' is:

a. new variable declaration

b. argument name

c. argument value

---------------------

3. The block

{
    text("Product")
}
from the previous question is:

a. block inside built-in syntax construction td

b. function literal (or "lambda")

c. something mysterious

---------------------

4. For the code

tr (color = "yellow") {
    this.td {
        text("Product")
    }
    td {
        text("Popularity")
    }
}
which of the following is true:

a. this code doesn't compile

b. this refers to an instance of an outer class

c. this refers to a receiver parameter TR of the function literal:

tr (color = "yellow") { TR.(): Unit -&gt;
      this.td {
          text("Product")
      }
}

1 to c, 2 to b, 3 to b, 4 to c

Generic functions

    import java.util.*

fun <t c: mutablecollection>&gt; Collection<t>.partitionTo(first: C, second: C, predicate: (T) -&gt; Boolean): Pair<c c> {
    for (element in this) {
        if (predicate(element)) {
            first.add(element)
        } else {
            second.add(element)
        }
    }
    return Pair(first, second)
}

fun partitionWordsAndLines() {
    val (words, lines) = listOf("a", "a b", "c", "d e").
            partitionTo(ArrayList<string>(), ArrayList()) { s -&gt; !s.contains(" ") }
    words == listOf("a", "c")
    lines == listOf("a b", "d e")
}

fun partitionLettersAndOtherSymbols() {
    val (letters, other) = setOf('a', '%', 'r', '}').
            partitionTo(HashSet<char>(), HashSet()) { c -&gt; c in 'a'..'z' || c in 'A'..'Z'}
    letters == setOf('a', 'r')
    other == setOf('%', '}')
}

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.