Idioms

A collection of random and frequently used idioms in Kotlin. If you have a favorite idiom, contribute it by sending a pull request.

Creating DTOs (POJOs/POCOs)

1. data class Customer(val name: String, val email: String)

provides a Customer class with the following functionality:

  • getters (and setters in case of vars) for all properties
  • equals()
  • hashCode()
  • toString()
  • copy()
  • component1(), component2(), …, for all properties (see Data classes)

Default values for function parameters

1. fun foo(a: Int = 0, b: String = "") { ... }

Filtering a list

1. val positives = list.filter { x -> x > 0 }

Or alternatively, even shorter:

1. val positives = list.filter { it > 0 }

Checking element presence in a collection.

1. if ("john@example.com" in emailsList) { ... }

3. if ("jane@example.com" !in emailsList) { ... }

String Interpolation

1. println("Name $name")

Instance Checks

1. when (x) {
2. is Foo -> ...
3. is Bar -> ...
4. else   -> ...
5. }

Traversing a map/list of pairs

1. for ((k, v) in map) {
2. println("$k -> $v")
3. }

k, v can be called anything.

Using ranges

1. for (i in 1..100) { ... }  // closed range: includes 100
2. for (i in 1 until 100) { ... } // half-open range: does not include 100
3. for (x in 2..10 step 2) { ... }
4. for (x in 10 downTo 1) { ... }
5. if (x in 1..10) { ... }

Read-only list

1. val list = listOf("a", "b", "c")

Read-only map

1. val map = mapOf("a" to 1, "b" to 2, "c" to 3)

Accessing a map

1. println(map["key"])
2. map["key"] = value

Lazy property

1. val p: String by lazy {
2. // compute the string
3. }

Extension Functions

1. fun String.spaceToCamelCase() { ... }

3. "Convert this to camelcase".spaceToCamelCase()

Creating a singleton

1. object Resource {
2. val name = "Name"
3. }

Instantiate an abstract class

1. abstract class MyAbstractClass {
2. abstract fun doSomething()
3. abstract fun sleep()
4. }

6. fun main() {
7. val myObject = object : MyAbstractClass() {
8. override fun doSomething() {
9. // ...
10. }

12. override fun sleep() { // ...
13. }
14. }
15. myObject.doSomething()
16. }

If not null shorthand

1. val files = File("Test").listFiles()

3. println(files?.size)

If not null and else shorthand

1. val files = File("Test").listFiles()

3. println(files?.size ?: "empty")

Executing a statement if null

1. val values = ...
2. val email = values["email"] ?: throw IllegalStateException("Email is missing!")

Get first item of a possibly empty collection

1. val emails = ... // might be empty
2. val mainEmail = emails.firstOrNull() ?: ""

Execute if not null

1. val value = ...

3. value?.let {
4. ... // execute this block if not null
5. }

Map nullable value if not null

1. val value = ...

3. val mapped = value?.let { transformValue(it) } ?: defaultValue
4. // defaultValue is returned if the value or the transform result is null.

Return on when statement

1. fun transform(color: String): Int {
2. return when (color) {
3. "Red" -> 0
4. "Green" -> 1
5. "Blue" -> 2
6. else -> throw IllegalArgumentException("Invalid color param value")
7. }
8. }

‘try/catch’ expression

1. fun test() {
2. val result = try {
3. count()
4. } catch (e: ArithmeticException) {
5. throw IllegalStateException(e)
6. }

8. // Working with result
9. }

‘if’ expression

1. fun foo(param: Int) {
2. val result = if (param == 1) {
3. "one"
4. } else if (param == 2) {
5. "two"
6. } else {
7. "three"
8. }
9. }

Builder-style usage of methods that return Unit

1. fun arrayOfMinusOnes(size: Int): IntArray {
2. return IntArray(size).apply { fill(-1) }
3. }

Single-expression functions

1. fun theAnswer() = 42

This is equivalent to

1. fun theAnswer(): Int {
2. return 42
3. }

This can be effectively combined with other idioms, leading to shorter code. E.g. with the when-expression:

1. fun transform(color: String): Int = when (color) {
2. "Red" -> 0
3. "Green" -> 1
4. "Blue" -> 2
5. else -> throw IllegalArgumentException("Invalid color param value")
6. }

Calling multiple methods on an object instance (with)

1. class Turtle {
2. fun penDown()
3. fun penUp()
4. fun turn(degrees: Double)
5. fun forward(pixels: Double)
6. }

8. val myTurtle = Turtle()
9. with(myTurtle) { //draw a 100 pix square
10. penDown()
11. for (i in 1..4) {
12. forward(100.0)
13. turn(90.0)
14. }
15. penUp()
16. }

Configuring properties of an object (apply)

1. val myRectangle = Rectangle().apply {
2. length = 4
3. breadth = 5
4. color = 0xFAFAFA
5. }

This is useful for configuring properties that aren’t present in the object constructor.

Java 7’s try with resources

1. val stream = Files.newInputStream(Paths.get("/some/file.txt"))
2. stream.buffered().reader().use { reader ->
3. println(reader.readText())
4. }

Convenient form for a generic function that requires the generic type information

1. //  public final class Gson {
2. //     ...
3. //     public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
4. //     ...

6. inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json, T::class.java)

Consuming a nullable Boolean

1. val b: Boolean? = ...
2. if (b == true) {
3. ...
4. } else {
5. // `b` is false or null
6. }

Swapping two variables

1. var a = 1
2. var b = 2
3. a = b.also { b = a }

TODO(): Marking code as incomplete

Kotlin’s standard library has a TODO() function that will always throw a NotImplementedError. Its return type is Nothing so it can be used regardless of expected type. There’s also an overload that accepts a reason parameter:

1. fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")

IntelliJ IDEA’s kotlin plugin understands the semantics of TODO() and automatically adds a code pointer in the TODO tool window.